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 d'une table dans Spring JPA?
Par exemple:SELECT projectId, projectName FROM projects
Vous pouvez définir nativeQuery = true
dans l'annotation @Query
à partir d'une classe Repository
comme suit:
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 standard mappée comme ceci, à moins que vous n'ayez réellement besoin que de ces deux valeurs:
public List<Project> findAll()
Cela vaut probablement la peine de regarder les données Spring docs également.
Je n'aime pas particulièrement la syntaxe (ça 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);
Ensuite, bien sûr, vous devez simplement fournir un constructeur pour Document qui accepte docId & nom de fichier comme argument de constructeur.
Vous pouvez utiliser des projections à partir de Spring Data JPA (doc) . Dans votre cas, créez une interface:
interface ProjectIdAndName{
String getId();
String getName();
}
et ajouter la méthode suivante à votre référentiel
List<ProjectIdAndName> findAll();
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é séparée sans les champs non 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 quelques 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 des colonnes.
J'imagine que le moyen le plus simple est peut-être 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 classements sans utiliser le langage * QL.
Comme vous pouvez le voir sur 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 l'utiliser comme si
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
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 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);
Avec les nouvelles versions de Spring, on peut procéder comme suit:
Si vous n'utilisez pas de requête native, procédez comme suit:
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 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 le docs
Vous pouvez appliquer le code ci-dessous dans votre classe d'interface de référentiel.
entityname signifie votre nom de table de base de données comme des projets. Et Liste signifie que le projet est la classe d'entité 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 la requête native SQL.
Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
La plupart des réponses suggèrent d'utiliser une variante de la requête SQL native. Cependant, en utilisant jpa Spring-Data intégré, nous pouvons également le réaliser:
Vous devez simplement utiliser la signature de méthode suivante dans la classe Repository.
ModelClass findBy$Column_1And$Column_2In(Object $col1Value, Object $col2Value );
Selon le schéma, il peut renvoyer une liste ou une seule instance. Cette approche peut être appliquée à une ou plusieurs colonnes, comme indiqué ci-dessus.
Pour votre exemple, cela pourrait être quelque chose comme:
Project findByProjectIdAndProjectNameIn(long projectId, String projectName);
projectId, nomprojet
Vous pouvez utiliser la réponse suggérée par @jombie et:
findAll()
à cette fin, mais utilisez le nom de votre choix;List
paramétré avec votre nouvelle interface (par exemple, List<SmallProject>
).tilisation de la requête native:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();