querydsl over collections In clause - java

I'm using querydsl over collections.
I'm trying to get all the elements that are contained in another list.
public class Parent {
private List<Child>;
}
public class Child {
private String key;
private String value;
}
Due a concrete list of Child objects (List<Child> lovedChilds), for each parent I need to select those childs are included in lovedChilds.
List<Parent> parents = ...;
for (Parent parent in parents)
{
select
from (child, parent.childs)
where lovedChilds contains a lovedChild
where child.getKey.equals(lovedChild.getKey);
}

Since you have an n:m relation you should have a cross table somewhere.
I asume it to be parent2child with the columns parent and child (foreign keys to the corresponding ID columns).
Simply perform a join:
select * from parent join parent2child join child where child.key in lovedChildren
If you want to get the parent objects only once, you can add a group by or a distinct.

Related

To Implement Parent/Child & get Set of records If i give parent name

I have data as shown as below. Here if Team 1 is parent & having 2 child Team A & Team B. Team A is again a parent & having player names as child. Team B does not have any child.
Again in another scenario, Team A is independent parent & contains some child etc..
If i give Team 1, then it should fetch records of Team A & Team B as a bundle.
If i give Team A, then it should fetch records of Team A containing its child.
I was thinking to implement this using Map or Tree . and I tried this -
public class Node {
private String id;
private List<Node> children = new ArrayList<>();
private Node parent;
..........
//setters and getters
}
but here creating node dynamically is problem because we don't know the levels of parents(in this example there are 2). means "Dhoni" again contains some child like wise.
How to implements this ?. Please guide.
Whatever i understood from problem description i will try to summarize here.You are looking for a data structure which can take parent name(key) and it might have children, and each child also further can be extended.
public class Node {
private String id; // for each level you have key defined.
private List<Node> children = new ArrayList<>(); //using given key you can get children list
}
You can use map here
Map<String, List<Node>> // here key is team name etc., and list represents children.
If you give team1 as key, you get list which contains teamA, teamB. So if you want to check further, check list size, if it is greater than zero, you can get children(Further you can get all the players defined for both teamA,teamB) otherwise you are at last child.

Specifying criteria for child table in One To Many Relationship

I have two entity objects (A and B) that have a One-To-Many relationship. I am using JPA (Hibernate) to join these tables and query them for a specific result set, but the criteria I specify for the child table (B) are not applied when fetching my results. This is how I have defined the query:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<A> query = builder.createQuery(A.class);
Root<A> a = query.from(A.class);
Join<A, B> abJoined = a.join(A_.b);
query.distinct(true)
.where(builder.and(
builder.equal(a.get(A_.id), id),
builder.equal(a.get(A_.active), 1),
builder.equal(a.get(A_.location), 1011),
builder.equal(a.get(A_.status), "Pending"),
builder.equal(abJoined.get(B_.status), "Not Moved"),
builder.greaterThan(abJoined.get(B_.detailId), 0)
));
When I call entityManager.createQuery(query).getResultList(); I get one instance of entity 'A', but when I try to access 'B' through 'A' a.getB() the two criteria that I had specified for abJoined are not applied and I get all instances of 'B' that are joined to 'A'. Is there something more I need to do to get these criteria applied? If the criteria cannot be applied, is there a recommended method for removing the corresponding instances of 'B' from the result set?
I can provide more code or other details if necessary.
The query is used to select which A entities must be returned by the query. But the A entities will never be partial entities containing only a subset of their Bs. They will always be complete instances of A, reflecting the state of what A is in the database, and which B this A is related to.
BTW, even if this was possible (it's not, and explicitely forbidden by the JPA spec), your query would at least have to load the Bs as well, using a fetch join. Otherwise only the state of A is returned by the query, and the linked Bs are loaded lazily.
But in JPA, for a #OneToMany relationship, Query is fired first on the master, with all the Criteria and fetches just master records.
Later Individually the query is fired, BUT BUT BUT......the B table criteria will not contain all the conditions, but only one condition i.e. just the primary key VALUE of master records fetched in i.e just with one condition "b.A_id=[primarykeyfetched from master]"
SOLUTION is simple
Make an Independent class, in which we require the fields of #OneToMany relationship
STEP 1
public class AB {
private A a;
private B b; //#OneToMany with A in the Entity class definitions
public AB(){}
public AB(A a, B b){ ///Very Important to have this constructor
this.a=a;
this.b=b;
}
getter setter....
}
STEP 2
CriteriaQuery<AB> q = criteriaBuilder.createQuery(AB.class);
Root<A> fromA = criteriaQuery.from(A.class);
List<Predicate> predicates = new ArrayList<Predicate>();
Join<A,B> fromB = fromA.join("b", JoinType.INNER);/*"b",fieldName of B in entity Class A*/
criteriaQuery.select(criteriaBuilder.construct(AB.class,A,B));//looks AB's 2 param constr.
predicates.add(criteriaBuilder.equal(fromA.get("name"), filter.getName()));
predicates.add(criteriaBuilder.equal(fromB.get("salary"), filter.getSalary()));
..........
List<AB> ABDataList = typedQuery.getResultList();
for(AB eachABData :ABDataList){
....put in ur objects
obj.setXXX(eachABData.getA().getXXX());
obj.setYYY(eachABData.getB().getYYY());
}
This will give all the results applying all the criteria to master table A, and comparing the primary key of Table B instead of foreign key.

Generate Nested List (Tree) from Flat List

I have a plain class named MenuModel in Java (it's for nested menu as the name suggests) like this:
public class MenuModel {
public String id;
public String parentId = null;
public String title;
public MenuModel parent = null;
public List<MenuModel> children = new ArrayList<MenuModel>();
}
My code fetch data from web API and generate a flat list of MenuModel with only id, parentId, and title fields filled with data. However, I need each MenuModel to have references to its parent and (optionally) children for further uses.
I have thought of a method which make a nested loop to pair the models each other and check if they are parent and child. But I think that costs too much (n^2 or n^3 complexity, the itemset is large) and can only fill the parent field.
What is the best way to achieve this in Java? To summarize:
Input: ArrayList<MenuModel> source
Output: ArrayList<MenuModel> result containing all MenuModel from source which has parentId = null (that means, it's top level menu), with each MenuModel has children fields filled with reference to their respective children MenuModel. Additionally, each children have reference to their parents.
Thanks in advance
Go through all the records and add them to a HashMap<String, MenuModel> (the key being the ID).
Then, for each record record:
Look up the parent ID in the above map to get parent.
Assign the parent to this record's parent variable - record.parent = parent.
Add this record to the parent's list of children - parent.children.add(record).
Running time: Expected O(n).

JPA parent child relationship

I have a scenario where I need to load all the child values in one case and some specific child values in other . I am using a single bean for both the cases and writing the queries using named query.
#namedqueries{
#namedQuery(name="query1") = "select parent from Parent parent",
#namedQuery(name="query2") = "select parent from Parent parent",
}
Class Parent {
#manytomany
#join mentioned my join condition here //
List<Child> child ;
}
Class Child
{
String A;
String B;
String C;
#manytomany(mappedby = "child")
List<parent> parent ;
}
Now in my query 2 I need to load only String A not String B and String C .
I tried using
"select parent.child .A from Parent parent" as Query 2
but getting the below error
"Attempting to navigate to relation field via multi-valued association and
jpql doesnt allow traversal through multi valued relationship. Try join instead"
So any suggestions on how to proceed on this ..
1) Should I have to create a new bean for each Query
2) Or Can we control the child object parameters in specific named queries
You are accessing a collection when you say select parent.child and you can't say select parent.child.A this is wrong according HQL standards. You need to do this using join as the error message is suggesting:
select c.A from parent as p join p.child as c
Then no, you don't have to create a new bean for each query.

Hibernate: updating child object

I have such structure:
// all objects have valid mapping to database
public class Child {
private int id;
private String name;
}
public class Parent {
private int id;
private String name;
private List<Child> chidlren;
}
and I have to update specific child B inside parent A.
There are two ways:
Update child's fields inside collection and update the whole object:
Parent temp = dao.getParent(id);
temp.getChildren.get(0).setName('test');
dao.updateParent(temp);
Update only child object:
Child temp = dao.getChild(id);
temp.setName('test');
dao.updateChild(temp);
Which one is better if I want to get more perfomance?
Thank you
On the surface, I would surmise that the second solution
2.Update only child object
would be more performant.
However, the only way you determine this quantitatively would be to turn on Hibernate's show_sql, capture the SQL for Solution 1 and Solution 2, run an Explain Plan for each of your solutions, and compare the resulting Explain Plans.
You could get differing results depending on what else has changed/not changed in the Parent object and other children in the Parent.children collection. When capturing SQL for Explain Plans, you would want to try different scenarios.

Categories

Resources