Learning how to write JPA query. Please advise me whether it possible to write the below queries more efficiently, may be in a single select statement. May be a join, but not sure how to do it.
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
}
Queries:
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();
Both the queries work. Query 1 returns a list of groups, where the person (mgr1) has a relation MANAGER with. Query 2 returns all the Persons they are CUSTOMER to the groups returned by query 1. In effect, I get a list of Person they are belong to (customer) the same group where the Person (mgr1) has a relation MANAGER with.
Is it possible to combine them into single sql statement so possibly only one db access?
You literally nest one query inside the other, and use a “where in” clause to specify that the outer query should fetch customers from the inner query.
Your calling code passes
typeName,typeName2, andpartyFromparameters as before.PartyToparameter is not needed, since the data comes from the subselect (inner query.)You can achieve the same thing using a self join, with a where clause that filters managers on the left side, and customers on the right side, but using an ‘in’ clause is semantically clearer.
EDIT: I addded .id to the subselect, which I think is needed.