Sto usando Spring JPA per eseguire tutte le operazioni del database. Tuttavia, non so come selezionare colonne specifiche da una tabella in Spring JPA?
Per esempio:
SELECT projectId, projectName FROM projects
Sto usando Spring JPA per eseguire tutte le operazioni del database. Tuttavia, non so come selezionare colonne specifiche da una tabella in Spring JPA?
Per esempio:
SELECT projectId, projectName FROM projects
Risposte:
Puoi impostare nativeQuery = true
l' @Query
annotazione da una Repository
classe come questa:
public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";
@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();
Nota che dovrai fare tu stesso la mappatura. Probabilmente è più semplice utilizzare la normale ricerca mappata in questo modo, a meno che non siano necessari solo questi due valori:
public List<Project> findAll()
Probabilmente vale la pena guardare anche i documenti di dati di Spring .
FIND_PROJECTS
) con il value
nome dell'attributo (quindi se questo fosse il mio codice avrei dovuto scriverlo come @Query(value = FIND_PROJECTS, nativeQuery = true)
, ecc.
È possibile utilizzare le proiezioni dal JPA (doc) di Spring Data . Nel tuo caso, crea un'interfaccia:
interface ProjectIdAndName{
String getId();
String getName();
}
e aggiungi il seguente metodo al tuo repository
List<ProjectIdAndName> findAll();
In particolare la sintassi non mi piace (sembra un po 'confusa ...) ma questa è la soluzione più elegante che sono riuscito a trovare (utilizza una query JPQL personalizzata nella classe di repository 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);
Quindi, naturalmente, devi solo fornire un costruttore Document
che accetti docId
e filename
come sostiene il costruttore.
Nella mia situazione, ho solo bisogno del risultato json e questo funziona per me:
public interface SchoolRepository extends JpaRepository<School,Integer> {
@Query("select s.id, s.name from School s")
List<Object> getSchoolIdAndName();
}
nel controller:
@Autowired
private SchoolRepository schoolRepository;
@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
List<Object> schools = schoolRepository.getSchoolIdAndName();
return schools;
}
Object
con un'interfaccia personalizzata come descritto da mpr. funziona perfettamente
Nel mio caso ho creato una classe di entità separata senza i campi che non sono richiesti (solo con i campi richiesti).
Mappa l'entità sulla stessa tabella. Ora, quando sono necessarie tutte le colonne, utilizzo la vecchia entità, quando sono necessarie solo alcune colonne, utilizzo l'entità lite.
per esempio
@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;
}
Puoi creare qualcosa come:
@Entity
@Table(name = "user")
Class UserLite{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
}
Funziona quando conosci le colonne da recuperare (e questo non cambierà).
non funzionerà se devi decidere dinamicamente le colonne.
Immagino che il modo più semplice sia usare QueryDSL , fornito con Spring-Data.
Usando la tua domanda la risposta può essere
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));
}}
Il gestore entità può essere Autowired e lavorerai sempre con oggetti e clase senza usare il linguaggio * QL.
Come puoi vedere nel link, l'ultima scelta sembra, quasi per me, più elegante, cioè usare DTO per memorizzare il risultato. Applica al tuo esempio che sarà:
JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));
Definire ProjectDTO come:
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(){....}
}
Con le versioni Spring più recenti Uno può fare come segue:
Se non si utilizza la query nativa, è possibile procedere come di seguito:
public interface ProjectMini {
String getProjectId();
String getProjectName();
}
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query("SELECT p FROM Project p")
List<ProjectMini> findAllProjectsMini();
}
Utilizzando la query nativa si può fare lo stesso come di seguito:
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
List<ProjectMini> findAllProjectsMini();
}
Per i dettagli, consultare i documenti
Secondo me questa è un'ottima soluzione:
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
e usandolo così
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
Utilizzando Spring Data JPA è disponibile una disposizione per selezionare colonne specifiche dal database
---- In DAOImpl ----
@Override
@Transactional
public List<Employee> getAllEmployee() throws Exception {
LOGGER.info("Inside getAllEmployee");
List<Employee> empList = empRepo.getNameAndCityOnly();
return empList;
}
---- In Repo ----
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
@Query("select e.name, e.city from Employee e" )
List<Employee> getNameAndCityOnly();
}
Nel mio caso ha funzionato al 100%. Grazie.
Puoi usare JPQL:
TypedQuery <Object[]> query = em.createQuery(
"SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);
List<Object[]> results = query.getResultList();
oppure puoi usare la query sql nativa.
Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
È possibile applicare il codice seguente nella classe dell'interfaccia del repository.
nome entità indica il nome della tabella del database come i progetti. E Lista indica che Progetto è la classe Entità nei tuoi Progetti.
@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);
Utilizzo della query nativa:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
Puoi usare la risposta suggerita da @jombie e:
findAll()
metodo per questo scopo ma usare il nome di tua scelta;List
parametro con la tua nuova interfaccia (ad es List<SmallProject>
.).