Question

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 dans une table dans Spring JPA ?

Par exemple:
SELECT projectId, projectName FROM projects

Était-ce utile?

La solution

Vous pouvez définir nativeQuery = true dans le @Query annotation d'un Repository classe comme ceci :

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 effectuer le mappage vous-même.Il est probablement plus facile d'utiliser simplement la recherche mappée standard comme celle-ci, à moins que vous n'ayez vraiment besoin que de ces deux valeurs :

public List<Project> findAll()

Cela vaut probablement la peine de regarder les données du printemps documents aussi.

Autres conseils

Vous pouvez utiliser les 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 du 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);

Ensuite bien sûr, il vous suffit de fournir un constructeur pour Document qui accepte docId & filename comme le prétend le constructeur.

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;
}

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é à la même table.Désormais, lorsque toutes les colonnes sont requises, j'utilise l'ancienne entité, lorsque seules certaines colonnes sont requises, j'utilise l'entité allégée.

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 va pas changer).

ne fonctionnera pas si vous devez décider dynamiquement des colonnes.

Je suppose que le moyen le plus simple consiste peut-être à utiliser RequêteDSL, 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 Autowired 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 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éfinir 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(){....}
}

À mon avis, c'est une excellente solution :

interface PersonRepository extends Repository<Person, UUID> {

    <T> Collection<T> findByLastname(String lastname, Class<T> type);
}

et je l'utilise comme ça

void someMethod(PersonRepository people) {

  Collection<Person> aggregates =
    people.findByLastname("Matthews", Person.class);

  Collection<NamesOnly> aggregates =
    people.findByLastname("Matthews", NamesOnly.class);
}

Avec les nouvelles versions de Spring, on peut procéder comme suit :

Si vous n'utilisez pas de requête native, cela peut être effectué 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 une requête native, la même chose peut être effectuée 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, vérifiez le documents

Using Spring Data JPA there is a provision to select specific columns from 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();
}

It worked 100% in my case.
Thanks.

Il est possible de préciser null comme valeur de champ en 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 la classe d'interface de votre référentiel.

Le nom d'entité 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);

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();

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 :

  • placez l'interface dans un fichier séparé, en dehors de la classe d'entité ;
  • utiliser ou non une requête native (le choix dépend de vos besoins) ;
  • ne remplacez pas findAll() méthode à cet effet mais utilisez le nom de votre choix ;
  • n'oubliez pas de retourner un List paramétré avec votre nouvelle interface (par ex. List<SmallProject>).
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top