J'utilise Spring JPA pour effectuer toutes les opérations de base de données. Cependant, je ne sais pas comment sélectionner des colonnes spécifiques à partir d'une table dans Spring JPA?
Par exemple:
SELECT projectId, projectName FROM projects
J'utilise Spring JPA pour effectuer toutes les opérations de base de données. Cependant, je ne sais pas comment sélectionner des colonnes spécifiques à partir d'une table dans Spring JPA?
Par exemple:
SELECT projectId, projectName FROM projects
Réponses:
Vous pouvez définir nativeQuery = true
dans l' @Query
annotation à partir d'une Repository
classe comme celle-ci:
public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";
@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();
Notez que vous devrez cependant faire le mappage vous-même. Il est probablement plus facile d'utiliser simplement la recherche mappée régulière comme celle-ci, sauf si vous n'avez vraiment besoin que de ces deux valeurs:
public List<Project> findAll()
Cela vaut probablement la peine de consulter également les documents de données Spring .
FIND_PROJECTS
) avec le value
nom de l' attribut (donc si c'était mon code, j'aurais dû l'écrire comme @Query(value = FIND_PROJECTS, nativeQuery = true)
, etc.
Vous pouvez utiliser des projections de Spring Data JPA (doc) . Dans votre cas, créez une interface:
interface ProjectIdAndName{
String getId();
String getName();
}
et ajoutez la méthode suivante à votre référentiel
List<ProjectIdAndName> findAll();
Je n'aime pas particulièrement la syntaxe (elle a l'air un peu hacky ...) mais c'est la solution la plus élégante que j'ai pu trouver (elle utilise une requête JPQL personnalisée dans la classe de référentiel 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);
Alors bien sûr, il vous suffit de fournir un constructeur pour Document
qui accepte docId
& en filename
tant que constructeur args.
Dans ma situation, je n'ai besoin que du résultat json, et cela fonctionne pour moi:
public interface SchoolRepository extends JpaRepository<School,Integer> {
@Query("select s.id, s.name from School s")
List<Object> getSchoolIdAndName();
}
dans le contrôleur:
@Autowired
private SchoolRepository schoolRepository;
@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
List<Object> schools = schoolRepository.getSchoolIdAndName();
return schools;
}
Object
par une interface personnalisée comme décrit par mpr. fonctionne parfaitement
Dans mon cas, j'ai créé une classe d'entité distincte sans les champs qui ne sont pas obligatoires (uniquement avec les champs obligatoires).
Mappez l'entité sur la même table. Maintenant, lorsque toutes les colonnes sont requises, j'utilise l'ancienne entité, lorsque seules certaines colonnes sont requises, j'utilise l'entité lite.
par exemple
@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;
}
Vous pouvez créer quelque chose comme:
@Entity
@Table(name = "user")
Class UserLite{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
}
Cela fonctionne lorsque vous connaissez les colonnes à récupérer (et cela ne changera pas).
ne fonctionnera pas si vous devez décider dynamiquement les colonnes.
Je suppose que le moyen le plus simple est d'utiliser QueryDSL , fourni avec Spring-Data.
En utilisant votre question, la réponse peut être
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));
}}
Le gestionnaire d'entités peut être câblé automatiquement et vous travaillerez toujours avec des objets et des classes sans utiliser le langage * QL.
Comme vous pouvez le voir dans le lien, le dernier choix me semble, presque pour moi, plus élégant, c'est-à-dire utiliser DTO pour stocker le résultat. Appliquez à votre exemple qui sera:
JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));
Définition de ProjectDTO comme:
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(){....}
}
Avec les nouvelles versions de Spring, on peut faire ce qui suit:
Si vous n'utilisez pas de requête native, cela peut être fait comme ci-dessous:
public interface ProjectMini {
String getProjectId();
String getProjectName();
}
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query("SELECT p FROM Project p")
List<ProjectMini> findAllProjectsMini();
}
En utilisant la requête native, la même chose peut être faite comme ci-dessous:
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
List<ProjectMini> findAllProjectsMini();
}
Pour plus de détails, consultez la documentation
À mon avis, c'est une excellente solution:
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
et l'utiliser comme ça
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
En utilisant Spring Data JPA, il est possible de sélectionner des colonnes spécifiques dans la base de données
---- Dans DAOImpl ----
@Override
@Transactional
public List<Employee> getAllEmployee() throws Exception {
LOGGER.info("Inside getAllEmployee");
List<Employee> empList = empRepo.getNameAndCityOnly();
return empList;
}
---- En Repo ----
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
@Query("select e.name, e.city from Employee e" )
List<Employee> getNameAndCityOnly();
}
Cela a fonctionné à 100% dans mon cas. Merci.
Vous pouvez utiliser JPQL:
TypedQuery <Object[]> query = em.createQuery(
"SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);
List<Object[]> results = query.getResultList();
ou vous pouvez utiliser une requête SQL native.
Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
Il est possible de spécifier null
comme valeur de champ dans SQL natif.
@Query(value = "select p.id, p.uid, p.title, null as documentation, p.ptype " +
" from projects p " +
"where p.uid = (:uid)" +
" and p.ptype = 'P'", nativeQuery = true)
Project findInfoByUid(@Param("uid") String uid);
Vous pouvez appliquer le code ci-dessous dans votre classe d'interface de référentiel.
entityname signifie le nom de votre table de base de données, comme les projets. Et List signifie que Project est la classe Entity dans vos projets.
@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);
Utilisation de la requête native:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
Vous pouvez utiliser la réponse suggérée par @jombie, et:
findAll()
méthode à cet effet mais utilisez le nom de votre choix;List
paramétré avec votre nouvelle interface (par exemple List<SmallProject>
).