I have object called 'MasterObj'. In that 'MasterObj', I have a child object called 'EmployeeObj'(foreign Key)
The relation ship between 'MasterObj' and 'EmployeeObj' is one to Many.
And my 'MasterObj' had so many duplicate 'employeeObj'
I need a count of MasterObj with DISTINCT or without duplication of emp_SlNo
How can I filter the duplicate emp_SlNo from my MasterObj using hibernate criteria.
Sorry for the my bad english.
Thanks in adance.
After so much of google, finally I got this code:
ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("id.state"));
projList.add(Projections.property("id.uspsCity"));
criteria.setProjection(Projections.distinct(projList));
And it works fine for me.
It eliminates the duplicate child object from parent objects.
Related
Entity ObjA has a One-To-Many relationship with another entity ObjB.
The following code in my dao works as expected:
Session session = getSessionFactory().openSession();
Criteria criteria = session.createCriteria(ObjA);
//......
criteria.setReadOnly(true);
criteria.setCacheable(false);
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
List<ObjA> results = criteria.list();
To optimize above code (to avoid OutOfMemoryException), I tried using ScrollableResults instead of criteria.list():
//same as above code..
ScrollableResults results = criteria.scroll(ScrollMode.FORWARD_ONLY);
while(results.next()){
ObjA a = results.get()[0];
session.evict(a);
//store 'a' in a collection
}
However, using this approach, I ended up getting individual rows for each ObjB corresponding to ObjA (in a sense, duplicate root entities). I tried not evicting the entity, but still got duplicate rows.
Any idea what I am doing wrong/missing here?
P.S. Hibernate version - 3.5.1-FINAL
Seems like this is a never-ending bug/required enhancement in hibernate.
I ended up using fetch="select" for all one-to-many joins.
Although this increased the db queries, but removed the duplicate root entities.
I'm trying to use Hibernate criteria without joining the sub-classes. Here is my case:
Notification.hbm.xml has the relation:
<many-to-one name="myObject" class="MyObject" column="MY_OBJECT_UID" not-null="true" index="NOTIFICATIONS_OBJECT" foreign-key="NOTIFICATIONS_OBJECT"/>
my JAVA code:
1. Criteria criteria = session.createCriteria(Notification.class.getName());
2. criteria.createAlias("myObject", "myObject", CriteriaSpecification.LEFT_JOIN);
3. criteria.addOrder(Order.desc("myObject.name").ignoreCase());
4. List<Notification> res = (List<Notification>) criteria.list();
If i remove lines 2 and 3 i get the result without joining MyObject, but if i add them, then the query is massive and doing Join with all of MyObject sub classes (and there are many).
I need a solution to avoid those Hibernate joins. One join for MyObject is OK (although not necessary), but Join to every subClass of it, is bad.
What are my option here?
Thanks.
One solution is to use projection, to query only the field you need
ProjectionList properties = Projections.projectionList();
properties.add(Projections.property("property1").as( "property1"));
...
criteria.setProjection(properties);
criteria.setResultTransformer(new AliasToBeanResultTransformer(Notification.class));
You can map it, to you domain Object but its is better to map it to custom DTO like a NotificationDTO, because it won't be managed entity but simple pojo:
You won't be able to update/ delete it. But if you need the data in "read only" mode its the best solution.
i have a Criteria like this
final Criteria criteria = session.createCriteria(Computer.class)
final Criteria studentCriteria = criteria.createCriteria("student","s");
final Criteria schoolCriteria = studentCriteria.createCriteria("school");
everything works OK. but in SchoolCriteria i need the Address which is a property of the School entity
my question is why this is not working
schoolCriteria.setFetchMode("address",FetchMode.JOIN);
i could not see the JOIN in the SQL statement
i just thought that if i am already in the schoolCriteria i could just get the address..
but this is working
criteria.setFetchMode("student",FetchMode.JOIN);criteria.setFetchMode("student.school",FetchMode.JOIN);criteria.setFetchMode("student.school.address",FetchMode.JOIN);
why this.
i am using Hibernate 4.1.5
thanks a lot.
Because you cannot directly fetch child object without fetching parent. when you are trying to do schoolCriteria.setFetchMode("address",FetchMode.JOIN); means you want address object (which is a property of the School entity) after even session get closed but school object is loaded so how can you set address object into student.
You have to do like JamesB given, Read More # Spring Roo doesn't add FetchType.LAZY for fields in .aj files, Should I do it manually?
I think you need to chain the joins together like this:
session.createCriteria(Computer.class)
.setFetchMode("student", FetchMode.JOIN)
.setFetchMode("school", FetchMode.JOIN)
.setFetchMode("address", FetchMode.JOIN)
I've "Student" and "Class" in relation many to many. In between there is a linking table.
If I want to retrieve all the students with HQL in the following way, everything is fine:
Query queryObject = getSession().createQuery("from Student");
return queryObject.list();
With the above code if there are three students I get a list of three students.
If I use criterias, however, it's fine only as long as there are no associations in the linking table.
Criteria crit = getSession().createCriteria(Student.getClass());
return crit.list();
With the second code, I get three results only when the linking table is empty. However when I add an association, I get 6 results. Looking at the log, Hibernate generates multiple selects. How is it possible?
Can someone explain why does this happen? How can I fix the criteria in order to return the three records only once?
EDIT
In the Student class I mapped in this way:
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(
name="room_student_rel"
, joinColumns={
#JoinColumn(name="id_student")
}
, inverseJoinColumns={
#JoinColumn(name="id_room")
}
)
private List<Room> rooms;
In the room (class) I mapped in this way:
#OneToMany(fetch=FetchType.EAGER, mappedBy="room")
#Fetch(FetchMode.SELECT)
private List<RoomStudent> roomStudents;
To expand on my previous comment, Hibernate will try to select using an outer join when the FetchType is set to EAGER.
See 2.2.5.5 at the following:
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
For the implications of this see here:
Hibernate Criteria returns children multiple times with FetchType.EAGER
Now you can also specify a FetchMode (on your criteria.setFetchMode("assocFiled",FetchMode.LAZY) ) to set it to something other than JOIN or you can use something like criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); to filter the duplicates.
Ideally you should avoid EAGER on your entity mappings and where eager fetching is required enable it explicitly on entity load using some hint or via FetchProfile and then deal with the duplicates if required.
i have two entities named Parent and Child, linked in a one-to-many relationship. The Child entity has a boolean isStudent property.
How do i get, using the Hibernate Criteria API, all the Parent entities that have at least one Child with isStudent = true?
I was trying to use a Projection object to count all the parents that have at least one Child with the property correctly set, and then return those whose row count is greater than zero, like in the following piece of code (which doesn't work, though):
Criteria criteria = getCurrentSession().createCriteria(Parent.class);
criteria.setProjection(Projections.alias(Projections.rowCount(), "count"))
.add(Restrictions.gt("count", 0)).createCriteria("children")
.add(Restrictions.eq("isStudent", true));
Thanks for your help
This worked for me:
DetachedCriteria crit = DetachedCriteria.forClass( Parent.class, "theparent" );
DetachedCriteria countSubquery = DetachedCriteria.forClass( Child.class , "child" );
countSubquery
.add( Property.forName("theparent.id").eqProperty( "parent.id" ) )
.setProjection(Projections.count("id"));
crit.add(Subqueries.lt(Long.valueOf(0), countSubquery));
[Edit: fixed a bug a pointed out by #brabenetz]
Where there is a bidirectional relation between Parent and Child, i.e. the Child has a field "parent"
It returns the Parents that have >0 children.
The Answer from RobAu is nearly what we needed.
But there is a small bug in it: Instead of Subqueries.gt(..) you need Subqueries.lt(...)
crit.add(Subqueries.lt(Long.valueOf(0), countSubquery));