How to add Distinct in Hibernate Criteria - java

In my database I have a Test table, with columns: testName, testType
there are 2 different tests with the same type I.e "SUN", so I want only one of them for which I use Distinct in my hibernate / criteria as below, but it still giving me both the types with the same name as "sun".
Criteria crit = session.createCriteria(Test.class);
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
crit.setResultTransformer(trans);
List rsList = trans.transformList(crit.list());
Any idea what could be the reason, or any other way of filtering duplicates.

Use Projections.distinct.
Criteria crit = session.createCriteria(Test.class).setProjection(
Projections.distinct(Projections.projectionList()
.add(Projections.property("type"), "type") )
.setResultTransformer(Transformers.aliasToBean(YourBean.class));
List lst = crit.list();
where YourBean.class has a property "type". The returned list will be List<YourBean>.

Try to use :
cr.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
It work perfectly for me

I finally have found out to get values of other columns:
Criteria criteria = session.createCriteria(Test.class);
ProjectionList projectionList = Projections.projectionList();
ProjectionList projectionList2 = Projections.projectionList();
projectionList2.add(Projections.distinct(projectionList.add(Projections.property("distinctColumn"), "distinctColumn")));
projectionList2.add(Projections.property("col1"), "col1");
projectionList2.add(Projections.property("col2"), "col2");
criteria.setProjection(projectionList2);
criteria.setResultTransformer(Transformers.aliasToBean(Test.class));
List list = criteria.list();

Try to use :
Criteria criteria =
session.createCriteria(Test.class).setProjection(
Projections.distinct(Projections.property("testType")));
List<Test> rsList = criteria.list();

Had the same problem and ended up solving using the Group By projection and then adding in all the columns I needed. For example
Criteria query = session.createCriteria(Class.class)
.setProjection(Projections.projectionList()
.add(Projections.groupProperty("Col1"), "Col1")
.add(Projections.groupProperty("Col2"), "Col2"))
.setResultTransformer(Transformers.aliasToBean(Class.class));
List list = query.list();

Try
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
Criteria crit = session.createCriteria(Test.class);
List list = crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();

Projections provide the result of the marked properties only. but, it creates problem for the child entities. See my post for the real problem I faced it.
Hibernate: Parent and Child relationship data structure

Try using:
criteria.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE);
It uses default hashcodes to find matches in results.
Thanks.

Related

Criteria Query for Unidirectional one to many association, searching with list of entities

I have Entities which contain Collections (OneToMany) which hold Person Entities. A person does not know to which Collection it belongs.
I want to search for MyPersons entities that contain specific Persons.
The problem is that I dont know how to search with criteria when I have a list of Persons that need to be mapped to the MyPerson Entities.
Excuse me for my bad english.
I hope someone can help.
data=Collection.stream().filter(f->f.getName().equals("name")).forEach(i->{
System.out.println();
});
I found a solution:
final CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<MyPersons> query = builder.createQuery(MyPersons.class);
Root<MyPersons> root = query.from(MyPersons.class);
Join<MyPersons, MyNaturalPerson> join = root.join("persons");
ParameterExpression<Collection> persons = builder.parameter(Collection.class);
//Persons = filled with MyPerson Entities
query.where(join.in(persons));
TypedQuery<MyPersons> tq = session.createQuery(query);
List<?> resultList = tq.setParameter(persons, result).getResultList();
List<MyNaturalPerson> finalresult = (List<MyNaturalPerson>) resultList;
Thx to a very similar Question/problem

Restrict selected fields using Hibernate Criteria projection

I have an HQL query, but it has many where conditions. So I decided to use Hibernate Criteria.
Here is my query:
select distinct u.employee.id,u.employee.name,u.employee.address.phone from user u.
I tried it using the Criteria Project.property. But it gives an error. Is it possible to write Hibernate Criteria for this query?
Criteria cr = session.createCriteria(User.class)
.setProjection(Projections.projectionList()
.add(Projections.property("employee.id"), "id")
.add(Projections.property("employee.name"), "Name"));
List<User> list = cr.list();
Few more examples.
Criteria cr = session.createCriteria(Employee.class);
// To get total row count.
cr.setProjection(Projections.rowCount());
// To get average of a property.
cr.setProjection(Projections.avg("salary"));
// To get distinct count of a property.
cr.setProjection(Projections.countDistinct("firstName"));
// To get maximum of a property.
cr.setProjection(Projections.max("salary"));
// To get minimum of a property.
cr.setProjection(Projections.min("salary"));
// To get sum of a property.
cr.setProjection(Projections.sum("salary"));
List<User> users = (List<User>) dbSession.createCriteria(User.class)
.add(Restrictions.eq("nameOfFieldInUserClass", value))
.list();
"nameOfFieldInUserClass" is name of restriction field in User, not name of column in DB.
and for distinct you can use
setProjection(Projections.distinct(Projections.property("nameOfField")));

Hibernate Projection on list Field/Attribute and Restricted.in

I am have the following product class
productClass
productID
name
make
title
colors {1..*}.
I'm trying to get
productID, colors and name field only..
I product works for single attirbute but colorList wasn't retrieve.
and worst of all.. when I have a criteria (restrictions.in) it says sql is not form properly.. missing attribute y1_
A good example will be
Hibernate criteria with projection not performing query for #OneToMany mapping
I am trying to get the PAYMENT with expenses intact using project where else he is trying to get some fields in expenses
If you want project any set of attributes for any item of color list, consider use http://github.com/moesio/seimos Here you are an example:
As an example, you can use criteria as follows:
Criteria criteria = session.createCriteria(Cat.class);
criteria.add(Restrictions.like(“description”, “Pap”)
.addOrder(Order.asc(“description”);
Criteria subCriteria = criteria.createCriteria("kind", "kind");
subCriteria.add(Restrictions.eq("description", "persa"));
Criteria anotherSubCriteria = subCriteria.createCriteria("anAssociation","anAssociation");
anotherSubCriteria.add(Restrictions.eq("attribute", "anything"));
criteria.setResultTransformer(new AliasToBeanResultTransformer(Cat.class));
criteria.crateAlias(“kind.anAssociation”, “kind_anAssociation”);
criteria.setProjection(Projections.projectionList()
.add(Projections.alias(Projections.property(“id”), “id”))
.add(Projections.alias(Projections.property(“kind.id”, “kind.id”))
.add(Projections.alias(Projections.property(“kind.anAssocation.attribute”, “kind.anAssociation.attribute”))
List cats = criteria.list();
But if you want save some code, you can use Seimos and code just
Filters filters = new Filters();
filters.add(new Filters(“description”, “Pap”)
.add(new Filter(“description”))
.add(new Filter("kind.description", "persa"))
.add(new Filter("kind.anAssociation.attribute", "anything"));
List<Cat> cats = dao.find(filters);
So, consider use http://github.com/moesio/seimos
If I understand you correctly, then you can use such query for your purposes:
List<Object[]> results = sess.createCriteria(Category.class, "category")
.add(Restrictions.in("category.name", new String[]{"Test1", "Test2"}))
.createAlias("items", "item")
.setProjection(Projections.projectionList()
.add(Projections.property("category.id"), "categoryId")
.add(Projections.property("category.name"), "categoryName")
.add(Projections.property("item.name"))
.add(Projections.property("item.initialPrice")))
.list();
It will return the list of Object[] arrays that represents each row of the result.
I don't know sructure of your Color entity and what fields you need from it thats why I posted example for two default entities: Category and Item (their relationship is one-to-many as in your case).
Instead of array you can use List. For example you can define resrictions in above example in such way:
List<String> inRestrictions = new ArrayList<String>();
inRestrictions.add("Test1");
inRestrictions.add("Test2");
...
.add(Restrictions.in("category.name", inRestrictions))
...
EDIT:
If you need Product object with list of colors for it then fetch only it. If you define correct mapping then Colors list will be fetched with it (lazily or eagerly).
List<Product> results = sess.createCriteria(Product.class)
.add(Restrictions.in("... necessary restrictions")
.list()

How to write following JPQL using Criteria?

Student - Course : OneToMany
JPQL :
select Student from Student student, Course course where
student.name=:STUDENTNAME and (course.courseName=:COURSENAME or
course.courseDuration=courseDuration)
Let us suppose one student might have 10 courses i want to retrieve only two records having Student - Courses(2).
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Student> criteriaQuery = criteriaBuilder.createQuery(Student.class);
Root<Student> studentRoot = criteriaQuery.from(Student.class);
studentRoot.fetch("courses", JoinType.LEFT);
Predicate condition = criteriaBuilder.equal(studentRoot.get("studentName"), "someName");
//how to add course condition here.
criteriaQuery.where(condition);
I Hope your Student entity has relation with Course mapping with property name course in student entity.
Here is Criteria Query
Criteria criteria = getSession().createCriteria(Student.class);
criteria.createAlias("course", "course");
criteria.add(Restrictions.eq("name", STUDENTNAME));
Criterion courseNameCrit = Restrictions.eq("course.courseName", courseName);
Criterion courseDurationCrit = Restrictions.eq("course.courseDuration", courseDuration);
criteria.add(Restrictions.disjunction().add(courseNameCrit).add(courseDurationCrit));
List<Student> studentList = criteria.list();
There is no equivalent of JPA QL “JOIN FETCH” in Criteria API.
JOIN FETCH uses EAGER fetch irrespective of the fetch type specified in the model annotation.
If you are using criteria api, you can call the getter method of child in the dao,so that it gets loaded.

What will be the Criteria for following SQL?

Can any one help me out with Criteria for following query :
SELECT * From TableA Inner Join TableB On TableA.ID=TableB.ID
I am trying with the following Criteria
Criteria criteria = session.createCriteria(TableA.class);
criteria.setFetchMode("TableB", FetchMode.JOIN);
The above criteria retrives both the table data.
Also if I need only specific columns from TableA how will the criteria Change ?
Thanks for your time.
Edit: TableA has one-to-many relationship with TableB.
Question doesn't make sense. In hibernate, the 2 Tables should actually be entities in which case they would have a relationship between them. Are you trying to randomly join 2 tables and get a result back? If so you have to use sql and use a ResultTransformer to convert the result into objects.
private ResultTransformer getResultsTransformer()
{
ResultTransformer transformer = new AliasToBeanResultTransformer(
MyResultBean.class) {
#Override
public Object transformTuple(Object[] values, String[] aliases)
{
MyResultBean row = new MyResultBean();
for (int i = 0; i < aliases.length; i++)
{
row.set(aliases[i], values[i]);
}
return (row);
}
};
return transformer;
}
Call this as follows:
Query q = session.createSQLQuery(sql);
q.setResultTransformer(getResultsTransformer());
List<MyResultBean> list = q.list();
UPDATE: If Table A has a 1-to-Many with Table B, then I find it easiest to use Alias
Criteria criteria = getSession().createCriteria(TableA.class);
criteria.createAlias("tableB","b");
criteria.add(Restrictions.eqProperty("id", "b.id");
criteria.list();
I hope this helps. Regards,
With JOIN, you need to indicate to Hibernate that you only want the "root entity", whcih is tableA. Add the following to your code:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

Categories

Resources