Hibernate criteria with 2 entities table and 1 association table - java

I need to make a query inside a DAO using hibernate criteria, but im not sure how.
I have 2 entities, A and B, and an association table, that contains both A and B ID's.
A doesnt know B, and B doesnt know A.
I want to find all A's that are associated with a certain B, using criteria.
I made a diagram, hope it helps to explain.
Example image
As you can see, table A have 3 records, table B have 3 records too and table AssocAB 3 records as well. I want to find all A's that are associated in AssocAB with B1. The query should return A1 and A3.
is it possible?
Here's the classes, and the relationship annotated.
Entity A: No annotation
Entity B: Have a Set of Entity A
#ManyToMany
#JoinTable(name = "Assoc_AB", joinColumns = { #JoinColumn(name = "ID_B")}, inverseJoinColumn = { #JoinColumn(name = "ID_A")})
#ForeignKey(name = "FK_A_B", inverseName = "FK_B_A")
public set<A> getA(){
return this.listOfA;
}
And no class for association class, the mapping on B creates the assoc table.
Thanks in advance.

I tried to write a criteria query with your indications, but it's not easy because you tell that A and B tables have a int ID, but then you put Strings in your rows ("A1", "B1"...). I supposed that your id is a String instead of an int. You should have something like this:
List<A> listOfA = new ArrayList<A>();
Criteria criteria = session.createCriteria(B.class, "b");
criteria.add(Restrictions.eq("b.id", "B1"));
List<B> listOfBs = criteria.list();
for (B b : listOfBs) {
listOfA.addAll(b.getA());
}
If you have a name property in B class, you would have to modify the restriction:
criteria.add(Restrictions.eq("b.name", "B1"));
I hope this code can help you solve your problem.

Related

Hibernate unidirectional One-to-many with multiple constraints

Suppose I have some generic tables apple, orange etc and a table note which contains notes about a row in one of my generic table. The note is stored by saving the entity_type (e.g. the table name) and entity_id (e.g. the id of the row).
I'm trying to make a unidirectional One-to-Many mapping from apple to note. Effectively creating this relationship:
SELECT *
FROM apple f
INNER JOIN note n
ON f.id = n.entity_id
AND n.entity_type = 'apple'
I've been trying something like:
#Entity
public class Apple {
...
#OneToMany
#JoinColumn(name = "entity_id", referencedColumnName = "id")
#WhereJoinTable(clause = "entity_type = 'apple'")
private Set<Note> changeNotes = new HashSet<>();
Which isn't working (error is #WhereJoinTable on an association without join table). Any ideas?
Update:
I think this is the sort of thing I"m trying to do https://docs.oracle.com/html/E13946_02/ref_guide_mapping_notes_nonstdjoins.html
However hibernate is looking for a column instead of just using the string...

how to return criteria Distinct Result

I have Bill and Bill_Details with onetomany and manytoone Relationship. I need a help in getting Bill List.
Pojo
Bill
#OneToMany(cascade={CascadeType.ALL},fetch = FetchType.EAGER)
#JoinColumn(name = "bill_id")
private Set<BillDetails> billDetails = new HashSet<BillDetails>();
BillDetails
#ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
#JoinColumn(name = "bill_id")
private Bill billId;
I am using Projections to take Bill value from List.
DaoHibernate
#Transactional
public List<Bill> getbillDetailsByBillId(String billId) {
Criteria cr = null;
try {
cr = getSession().createCriteria(Bill.class,"bill")
.createAlias("bill.billDetails","billDetails")
.setProjection(Projections.projectionList()
// I tried .setProjectionProjections.distinct(Projections.projectionList()
.add(Projections.property("billNo"),"billNo")
.add(Projections.property("billDetails.amount"),"billDetails.amount")
.add(Projections.property("billDetails.rate"),"billDetails.rate"))
.add(Restrictions.eq("id", billId))
.setResultTransformer(new AliasToBeanNestedResultTransformer(Bill.class));
} catch (Exception e) {
System.out.println("Get bill DetailsByBillId Error----------"+e);
e.printStackTrace();
}
System.out.println(cr.list().size());
return cr.list();
}
Note:
-- > Bill table contains single row
-- > BillDetails table contains four row for this BillId
My criteria Query Returns four Objects instead of single Object. I also tried with distinct feature.
Expected Output :
I need single object that contains BillDetails Objects(4 Values).
ie.I explained with sample Json format below
{billNo:231,
billDetails[{amount:100,rate:1}{amount:200,rate:2}
{amount:300,rate:30}{amount:400,rate:4}] }
How to get this by Hibernate criteria Query ? Please Help
First of all, your mapping isn't correct. You have a bidirectional association, and one of the side (the one side) must be the inverse of the one side:
#OneToMany(mappedBy = "billId", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<BillDetails> billDetails = new HashSet<BillDetails>();
You should also rename the field billId to bill, given that what it contains is a bill, and not a bill ID.
Now, the problem with your query is that you're using projections for no reason. When using projections, you deliberately choose to return rows containing individual columns. And since the SQL query returns 4 rows you get back 4 bills: one for each row.
You're also making your life unnecessarily complicated by using a Criteria query instead of HQL, which is much more suited for such simple static queries.
But even a HQL query is useless here, since you simply want to get a bill from its ID. All you need is
Bill bill = (Bill) session.get(Bill.class, billId);
This will get the bill, and since you chose to make the OneToMany association as EAGER, it will also immediately load its bill details.
If you hadn't made the association EAGER (and you should really leave it as LAZY), you could use this simple HQL query to load a bill with its details:
select distinct b from Bill bill
left join fetch bill.billDetails
where bill.id = :billId

Possible to perform a NOT IN for one-to-many relationship with Hibernate criteria?

I have a question about Hibernate and if it's possible to achieve the query using the Criteria API with the current data model structure I'm using. I have a data model with the following structure:
ParentClass contains a List:
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = org.test.ChildClass.class)
#JoinColumn(name = "child_uuid")
private List<ChildClass> childList = new ArrayList<ChildClass>();
The child class has one field:
private String testField
The query I'm attempting to write can be expressed as follows:
Return a list of all ParentClass objects that have the ABSENCE OF an object ChildClass that has a "testField" value of "1". In other words, there must not be an object in that list that has the testField value of 1.
Currently I have this query:
Criteria criteria = getSession().createCriteria(org.test.ParentClass);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.createAlias("childList", "c");
SimpleExpression expression = Restrictions.ne("c.testField", "1");
criteria.add(expression);
return (List<T>) criteria.list();
What happens is that I will get any ParentClass objects that contain at least one ChildClass that has a value of c.testField other than "1". This includes ParentClass objects that DO have a "testField" value of "1", which I'm trying to exclude entirely.
The table structure has ChildClass having a reference to ParentClass, but not vice versa. So it seems that each ChildClass object is joined with the ParentClass, and if they fulfill the above restriction, that ParentClass gets returned. This is the incorrect result as it means a ParentClass that has two ChildClass objects, one with value "1" and the other with value "2" will get returned.
Thanks for any help
You need the equivalent of the following HQL query:
select distinct p from Parent p
where not exists (select c.id from Parent p2 join p2.children c
where c.testField = '1' and p2.id = p.id)
You should be able to translate that to Criteria (if you really want to use criteria instead of using clearer HQL queries). You'll need to use Subqueries.notExists().
try with this one
Criteria criteria = getSession().createCriteria(org.test.ParentClass,"parent");
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.createAlias("parent.ChildClass", "pc");
SimpleExpression expression = Restrictions.ne("pc.testField", "1");
criteria.add(expression);
return (List<T>) criteria.list();

Hibernate Criteria. Join / Select when no Assosiation

I am using Hibernate version 4.2
I have 2 Entities.
#Entity
public class A {
Long Id;
#ManyToOne
B b;
}
#Entity
public class B {
Long Id;
//There is no relation back here with any annotations to A, and can't add a #OneToMany
}
is it possible todo a Query with Hibernate Criteria to get a result that looks like this.
List<Map<B,List<A>>> ? dosn't matter if it is with a join or a select.
example what i want in result:
A.id B.id
1 1,2,3,4
2
3 5
4 7
5
//Trind
You can use something like below. I don't know whether it is your actual requirement though. Assuming B b is OneToOne, 12 is the id of B,
Criteria c = session.createCriteria(A.class, "a");
c.createAlias("a.b", "b");
c.add(Restrictions.eq("a.b.Id", "12"));
return c.list();
this returns a list of arrays and by using those arrays you can form what you want.
I got help from Christian Bauer who have Written Hibernate in Action.
Criteria from Hibernate:
List<Object[]> result =
session.createCriteria(A.class, "a")
.createAlias("b", "i", JoinType.RIGHT_OUTER_JOIN)
.setResultTransformer(PassThroughResultTransformer.INSTANCE)
.list();

How in hql query select part of object?

I need tune query for performance. The tree of objects like:
classA {
classB b;
classC c;
.....}
I need select similar to SQL:
select a.field1, b.field2, c.field3, c.field4 from a left outer join b
on a.id=b.fk left outer join c on b.id=c.fk
I don't understand what kind of result will be returned, does it arrayList? Or query returns
all 3 objects?
Thanks.
It will be
List<Object[]> list = new ArrayList<Object[]>();
The result which would be returned by the query would be type of -
List<Object[]>
If you use HQL I think you use hibernate. Provide mapping with relations (ManyToOne or OneToOne) to your objects:
class A {
#ManyToOne
pribvate B b;
#OneToOne
private C c;
}
Then use session methods to select your object A with hql query of criteria. Hibernate do all joins for you automatically. And it will return List of A.

Categories