web-dev-qa-db-fra.com

Requête JPA sélectionnant uniquement des colonnes spécifiques sans utiliser la requête de critères?

Est-il possible de sélectionner, par exemple, uniquement les propriétés A et B d'un objet à l'aide d'une requête JPA sans utiliser les requêtes de critères?

Pour sélectionner toutes les propriétés, je ferais juste quelque chose comme:

SELECT i FROM ObjectName i WHERE i.id = 10

Mais j'ai un objet avec plusieurs propriétés sur un système existant et je souhaite n'en sélectionner que quelques-unes même si je suis conscient du fait que la sélection de plusieurs propriétés est généralement rapide.

Est-ce possible sans utiliser des requêtes de critères?

Je vous remercie!

41
Edy Bourne

Oui, comme dans plain SQL, vous pouvez spécifier le type de propriétés que vous souhaitez sélectionner:

SELECT i.firstProperty, i.secondProperty FROM ObjectName i WHERE i.id=10

L'exécution de cette requête retournera une liste de Object [], où chaque tableau contient les propriétés sélectionnées d'un objet.

Une autre méthode consiste à envelopper les propriétés sélectionnées dans un objet personnalisé et à les exécuter dans un TypedQuery:

String query = "SELECT NEW CustomObject(i.firstProperty, i.secondProperty) FROM ObjectName i WHERE i.id=10";
TypedQuery<CustomObject> typedQuery = em.createQuery(query , CustomObject.class);
List<CustomObject> results = typedQuery.getResultList();

Des exemples peuvent être trouvés dans this article.

MISE À JOUR 29.03.2018:

@Krish:

@PatrickLeitermann pour moi, c'est son attribution "Causée par: org.hibernate.hql.internal.ast.QuerySyntaxException: impossible de localiser la classe ***". comment résoudre ceci?

Je suppose que vous utilisez JPA dans le contexte d’une application Spring, n’est-ce pas? Certaines autres personnes avaient exactement le même problème et leur solution consistait à ajouter le nom complet (par exemple, com.example.CustomObject) après SELECT NEW mots-clés.

Peut-être que l'implémentation interne du framework de données Spring ne reconnaît que les classes annotées avec @ Entity ou enregistrées dans un fichier orm spécifique par leur nom simple, ce qui entraîne l'utilisation de cette solution de contournement.

83
Patrick Leitermann

Vous pouvez utiliser quelque chose comme ceci:

List<Object[]> list = em.createQuery("SELECT p.field1, p.field2 FROM Entity p").getResultList();

alors vous pouvez le parcourir:

for (Object[] obj : list){
    System.out.println(obj[0]);
    System.out.println(obj[1]);
}

MAIS Si vous n'avez qu'un seul champ dans la requête, vous obtenez une liste du type non provenant de Object [].

17
pL4Gu33

Excellente réponse! J'ai un petit ajout. En ce qui concerne cette solution:

TypedQuery<CustomObject> typedQuery = em.createQuery(query , String query = "SELECT NEW CustomObject(i.firstProperty, i.secondProperty) FROM ObjectName i WHERE i.id=100";
TypedQuery<CustomObject> typedQuery = em.createQuery(query , CustomObject.class);
List<CustomObject> results = typedQuery.getResultList();CustomObject.class);

Pour éviter une erreur de classe non trouvée, insérez simplement le nom complet du paquet. En supposant que org.company.directory est le nom de package de CustomObject:

String query = "SELECT NEW org.company.directory.CustomObject(i.firstProperty, i.secondProperty) FROM ObjectName i WHERE i.id=10";
TypedQuery<CustomObject> typedQuery = em.createQuery(query , CustomObject.class);
List<CustomObject> results = typedQuery.getResultList();
8
sagneta

Projections peut être utilisé pour sélectionner uniquement des propriétés spécifiques (colonnes) d'un objet entité.

De la docs

Les référentiels de données Spring renvoient généralement le modèle de domaine lors de l'utilisation de méthodes de requête. Cependant, il peut parfois être nécessaire de modifier la vue de ce modèle pour diverses raisons. Dans la section this , vous apprendrez à définir des projections pour afficher des vues simplifiées et réduites de ressources.

Définissez une interface avec uniquement le getters que vous voulez.

interface CustomObject {  
    String getA(); // Actual property name is A
    String getB(); // Actual property name is B 
}

Maintenant, retournez CustomObject depuis votre dépôt de la manière suivante:

public interface YOU_REPOSITORY_NAME extends JpaRepository<YOUR_ENTITY, Long> {
    CustomObject findByObjectName(String name);
}
7
Abdullah Khan

Je suppose que vous pourriez regarder ce lien si j'ai bien compris votre question http://www.javacodegeeks.com/2012/07/ultimate-jpa-queries-and-tips-list-part_09.html

Par exemple, ils ont créé une requête du type:

 select id, name, age, a.id as ADDRESS_ID, houseNumber, streetName ' +
 20' from person p join address a on a.id = p.address_id where p.id = 1'
0
SerhatCan

Oui c'est possible. Tout ce que vous avez à faire est de changer votre requête en quelque chose comme SELECT i.foo, i.bar FROM ObjectName i WHERE i.id = 10. Le résultat de la requête sera un List du tableau de Object. Le premier élément de chaque tableau est la valeur de i.foo et le deuxième élément est la valeur i.bar. Voir la section correspondante de référence JPQL .

0
ez121sl