2010-07-29 5 views
3

Apprendre comment écrire une requête JPA. S'il vous plaît me dire s'il est possible d'écrire les requêtes ci-dessous plus efficacement, peut-être dans une seule déclaration de sélection. Peut être une jointure, mais je ne sais pas comment le faire.comment écrire une requête JPA

class Relationship { 

    @ManyToOne 
    public String relationshipType; //can be MANAGER, CUSTOMER etc 

    @ManyToOne 
    public Party partyFrom; // a person who has a relation 

    @ManyToOne 
    public Party partyTo; // a group a person relate to 
} 

Requêtes:

 String sql = ""; 
     sql = "select rel.partyTo"; 
     sql += " from Relationship rel"; 
     sql += " where rel.partyFrom = :partyFrom"; 
     sql += " and rel.relationshipType= :typeName"; 
     Query query = Organization.em().createQuery(sql); 
     query.setParameter("partyFrom", mgr1); 
     query.setParameter("typeName", "MANAGER"); 
     List<Party> orgList = query.getResultList(); 

     String sql2 = ""; 
     sql2 = "select rel.partyFrom"; 
     sql2 += " from Relationship rel"; 
     sql2 += " where rel.partyTo = :partyToList"; 
     sql2 += " and rel.relationshipType = :typeName2"; 
     Query query2 = Organization.em().createQuery(sql2); 
     query2.setParameter("partyToList", orgList); 
     query2.setParameter("typeName2", "CUSTOMER"); 
     List<Party> personList2 = query2.getResultList(); 

Les deux requêtes fonctionnent. La requête 1 renvoie une liste de groupes, où la personne (mgr1) a une relation MANAGER avec. Requête 2 renvoie toutes les Personnes qu'ils sont CLIENT aux groupes retournés par la requête 1. En effet, j'obtiens une liste de Personne à laquelle ils appartiennent (client) le même groupe où la Personne (mgr1) a une relation MANAGER avec.

Est-il possible de les combiner en une seule instruction sql donc éventuellement un seul accès db?

Répondre

0

Vous imbriquez littéralement une requête dans l'autre et utilisez une clause "where in" pour spécifier que la requête externe doit extraire les clients de la requête interne.

select rel2.partyFrom 
from Relationship rel2 
where rel2.relationshipType = :typeName2 /* customer */ 
and rel2.partyTo.id in 
     (select rel.partyTo.id 
     from Relationship rel 
     where rel.partyFrom = :partyFrom 
     and rel.relationshipType = :typeName) 

Votre code d'appel passe typeName, typeName2 et partyFrom paramètres comme avant. PartyTo paramètre n'est pas nécessaire, car les données proviennent de la sous-sélection (requête interne)

Vous pouvez obtenir la même chose en utilisant une jointure automatique, avec une clause where qui filtre les gestionnaires sur le côté gauche et les clients sur la droite côté, mais en utilisant une clause 'in' est sémantiquement plus clair.

EDIT: J'ai ajouté .id à la sous-sélection, ce qui est selon moi nécessaire.

+0

merci !! .. était parfait (sans id - EDIT) .. acceptera la réponse, attendez de voir si quelqu'un commentaire sur la performance de requête interne .. si c'est la manière optimale de le faire .. merci encore – bsr

+0

La sous-requête sera rapide, puisqu'il ne s'agit pas d'une requête corrélée - elle est calculée une seule fois, comme avec votre code original. Juste aujourd'hui, j'ai remplacé un LEFT JOIN avec un WHERE IN et changé la performance de la requête de 18s à 5s sur le serveur SQL. Vous ne dites pas quelle base de données vous utilisez, mais en général une sous-requête peut surpasser une jointure lorsque vous effectuez un test d'existence et n'utilisez aucune des données. – mdma

+0

merci .. projet d'utiliser PostgreSQL ou Oracle .. J'utilise hibernate ORM, donc peut-être aussi compatible avec d'autres .. pouvez-vous élaborer sur un test d'existence vs n'utiliser aucune des données .. apprendre de nouveaux trucs tous les jours: -) merci .. – bsr

0

Ceci n'est pas une réponse à une question, mais aider quelqu'un d'autre si quelqu'un regarde dans @OneToMany relation dans Spring Data JPA utilisant JPQL, parce que la question est liée à JPA alors pensé à partager mes 2 cents, s'excuser à l'avance

@Entity 
@Table(name = "MY_CAR") 
public class MyCar { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

@Column(name = "DESCRIPTION") 
private String description; 

@Column(name = "MY_CAR_NUMBER") 
private String myCarNumber; 

@Column(name = "RELEASE_DATE") 
private Date releaseDate; 

@OneToMany(cascade = { CascadeType.ALL }) 
@JoinTable(name = "MY_CAR_VEHICLE_SERIES", joinColumns = @JoinColumn(name = "MY_CAR_ID "), inverseJoinColumns = @JoinColumn(name = "VEHICLE_SERIES_ID")) 
private Set<VehicleSeries> vehicleSeries; 
public MyCar() { 
    super(); 
    vehicleSeries = new HashSet<VehicleSeries>(); 
} 
// set and get method goes here 


@Entity 
@Table(name = "VEHICLE_SERIES ") 
public class VehicleSeries { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

@Column(name = "SERIES_NUMBER") 
private String seriesNumber; 

@OneToMany(cascade = { CascadeType.ALL }) 
@JoinTable(name = "VEHICLE_SERIES_BODY_TYPE", joinColumns = @JoinColumn(name = "VEHICLE_SERIES_ID"), inverseJoinColumns = @JoinColumn(name = "BODY_TYPE_ID")) 
private Set<BodyType> bodyTypes; 
public VehicleSeries() { 
    super(); 
    bodyTypes = new HashSet<BodyType>(); 
} 
// set and get method goes here 


@Entity 
@Table(name = "BODY_TYPE ") 
public class BodyType implements Serializable { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

@Column(name = "NAME") 
private String name; 
// set and get method goes here 


public interface MyCarRepository extends JpaRepository<MyCar, Long> { 
public Set<MyCar> findAllByOrderByIdAsc(); 

@Query(value = "select distinct myCar from MyCar myCar " 
     + "join myCar.vehicleSeries as vs join vs.bodyTypes as bt where vs.seriesNumber like %:searchMyCar% " 
     + "or lower(bt.name) like lower(:searchMyCar) or myCar.bulletinId like %:searchMyCar% " 
     + "or lower(myCar.description) like lower(:searchMyCar) " 
     + "or myCar.bulletinNumber like %:searchMyCar% order by myCar.id asc") 
public Set<MyCar> searchByMyCar(@Param("searchMyCar") String searchMyCar); 

}

Certaines données dans les tableaux comme

Select * from Vehicle_Series

ID  SERIES_NUMBER 
1  Yaris 
2  Corolla 

Select * from Body_Type

ID  NAME 
1  Compact 
2  Convertible 
3  Sedan 
Questions connexes