Używam Spring JPA do wykonywania wszystkich operacji na bazie danych. Jednak nie wiem, jak wybrać określone kolumny z tabeli w Spring JPA?
Na przykład:
SELECT projectId, projectName FROM projects
Używam Spring JPA do wykonywania wszystkich operacji na bazie danych. Jednak nie wiem, jak wybrać określone kolumny z tabeli w Spring JPA?
Na przykład:
SELECT projectId, projectName FROM projects
Odpowiedzi:
Możesz ustawić nativeQuery = true
w @Query
adnotacji z Repository
zajęć w ten sposób:
public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";
@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();
Pamiętaj jednak, że mapowanie będziesz musiał wykonać samodzielnie. Prawdopodobnie łatwiej jest po prostu użyć zwykłego odwzorowania, chyba że naprawdę potrzebujesz tylko tych dwóch wartości:
public List<Project> findAll()
Prawdopodobnie warto przyjrzeć się również dokumentacji Spring Data .
FIND_PROJECTS
) z value
nazwą atrybutu (stąd gdyby to był mój kod, musiałbym go zapisać jako @Query(value = FIND_PROJECTS, nativeQuery = true)
itp.
Możesz użyć prognoz z Spring Data JPA (doc) . W twoim przypadku stwórz interfejs:
interface ProjectIdAndName{
String getId();
String getName();
}
i dodaj następującą metodę do swojego repozytorium
List<ProjectIdAndName> findAll();
Nie podoba mi się szczególnie składnia (wygląda trochę hakersko ...), ale jest to najbardziej eleganckie rozwiązanie, jakie udało mi się znaleźć (używa niestandardowego zapytania JPQL w klasie repozytorium JPA):
@Query("select new com.foo.bar.entity.Document(d.docId, d.filename) from Document d where d.filterCol = ?1")
List<Document> findDocumentsForListing(String filterValue);
Wtedy oczywiście wystarczy dostarczyć konstruktor, Document
który akceptuje docId
& filename
jako argumenty konstruktora.
W mojej sytuacji potrzebuję tylko wyniku json, a to działa dla mnie:
public interface SchoolRepository extends JpaRepository<School,Integer> {
@Query("select s.id, s.name from School s")
List<Object> getSchoolIdAndName();
}
w kontrolerze:
@Autowired
private SchoolRepository schoolRepository;
@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
List<Object> schools = schoolRepository.getSchoolIdAndName();
return schools;
}
Object
niestandardowym interfejsem opisanym przez mpr. działa bez zarzutu
W moim przypadku utworzyłem oddzielną klasę encji bez pól, które nie są wymagane (tylko z polami, które są wymagane).
Zamapuj jednostkę na tę samą tabelę. Teraz, gdy wszystkie kolumny są wymagane, używam starej jednostki, gdy wymagane są tylko niektóre kolumny, używam jednostki lite.
na przykład
@Entity
@Table(name = "user")
Class User{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
@Column(name = "address", nullable=false)
Address address;
}
Możesz stworzyć coś takiego:
@Entity
@Table(name = "user")
Class UserLite{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
}
Działa to, gdy znasz kolumny do pobrania (i to się nie zmieni).
nie zadziała, jeśli musisz dynamicznie decydować o kolumnach.
Wydaje mi się, że najłatwiejszym sposobem jest użycie QueryDSL , które jest dostarczane z Spring-Data.
Odpowiedź może brzmieć na Twoje pytanie
JPAQuery query = new JPAQuery(entityManager);
List<Tuple> result = query.from(projects).list(project.projectId, project.projectName);
for (Tuple row : result) {
System.out.println("project ID " + row.get(project.projectId));
System.out.println("project Name " + row.get(project.projectName));
}}
Menedżer encji może być Autowiredem i zawsze będziesz pracować z obiektami i klasami bez używania języka * QL.
Jak widać w linku ostatni wybór wydaje się, prawie dla mnie, bardziej elegancki, to znaczy użycie DTO do przechowywania wyniku. Zastosuj do swojego przykładu, który będzie:
JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));
Definiowanie ProjectDTO jako:
class ProjectDTO {
private long id;
private String name;
@QueryProjection
public ProjectDTO(long projectId, String projectName){
this.id = projectId;
this.name = projectName;
}
public String getProjectId(){ ... }
public String getProjectName(){....}
}
W nowszych wersjach Spring można wykonać następujące czynności:
Jeśli nie używasz zapytania natywnego, możesz to zrobić w następujący sposób:
public interface ProjectMini {
String getProjectId();
String getProjectName();
}
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query("SELECT p FROM Project p")
List<ProjectMini> findAllProjectsMini();
}
Używając natywnego zapytania, można zrobić to samo, co poniżej:
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
List<ProjectMini> findAllProjectsMini();
}
Szczegółowe informacje można znaleźć w dokumentacji
Moim zdaniem to świetne rozwiązanie:
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
i używać go w ten sposób
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
Przy użyciu Spring Data JPA istnieje możliwość wybrania określonych kolumn z bazy danych
---- W DAOImpl ----
@Override
@Transactional
public List<Employee> getAllEmployee() throws Exception {
LOGGER.info("Inside getAllEmployee");
List<Employee> empList = empRepo.getNameAndCityOnly();
return empList;
}
---- W repozytorium ----
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
@Query("select e.name, e.city from Employee e" )
List<Employee> getNameAndCityOnly();
}
W moim przypadku zadziałało w 100%. Dzięki.
Możesz użyć JPQL:
TypedQuery <Object[]> query = em.createQuery(
"SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);
List<Object[]> results = query.getResultList();
lub możesz użyć natywnego zapytania sql.
Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
Możesz zastosować poniższy kod w klasie interfejsu repozytorium.
nazwa encji oznacza nazwę tabeli bazy danych, taką jak projekty. A Lista oznacza, że projekt jest klasą Entity w Twoich projektach.
@Query(value="select p from #{#entityName} p where p.id=:projectId and p.projectName=:projectName")
List<Project> findAll(@Param("projectId") int projectId, @Param("projectName") String projectName);
Korzystanie z natywnego zapytania:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
Możesz skorzystać z odpowiedzi sugerowanej przez @jombie i:
findAll()
metody w tym celu, ale użyj wybranej przez siebie nazwy;List
parametr sparametryzowany z nowym interfejsem (np List<SmallProject>
.).