Writing distinct in hibernate criteria - java

I want to write the below query using criteria .
I need to find the distinct rows and also use the current date in where clause .How can I achieve this in Criteria.
SELECT DISTINCT *
FROM EMAIL_PROGRAM
WHERE CURRENT_DATE >=PGM_START_DT
AND CURRENT_DATE <= PGM_END_DT
AND EMAIL_PGM_FLG ='Y'
AND EMAIL_PGM_DESC IS NOT NULL
and RGN_CD = 'US';
Below is my code in which I need to apply .
SessionFactory factory = null;
Session session = null;
try {
factory = getSessionFactory();
session = factory.openSession();
final Criteria criteria = session
.createCriteria(EmailDataBean.class);
returnList = criteria.list();
} catch (Exception e) {
logger.error(e.getMessage());
throw new DAOException(e);
} finally {
DBUtil.close(factory, session);
}
if (logger.isInfoEnabled()) {
logger.info(LOG_METHOD_EXIT);
}
return returnList;
}

you can use below on your criteria object.
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

You should do something like
//first add conditions in the where clause (you should use property names as defined in your Hbernate entities , not column names in your DB)
criteria.add(Restrictions.ge("PGM_START_DT", startDt));
criteria.add(Restrictions.le("PGM_END_DT", endDt));
criteria.add(Restrictions.eq("EMAIL_PGM_FLG", "Y"));
criteria.add(Restrictions.isNotNull("EMAIL_PGM_DESC"));
criteria.add(Restrictions.eq("RGN_CD", "US"));
Now, add every column (i.e. a Hibernate entity property/field) to a Projection list (this is needed to support distinct in the query)
ProjectionList pList = Projections.projectionList();
pList.add(Projections.property("PGM_START_DT"), "PGM_START_DT");
pList.add(Projections.property("PGM_END_DT"), "PGM_END_DT");
// add all the other properties (columns) and then have the Projections.distinct method act on the entire row (all the columns)
criteria.setProjection(Projections.distinct(pList));
By default, using Projections does return the result as a List<Object[]> rather than List<EmailDataBean>, which is usually not convenient. To remedy that, you should set a ResultTransformer
crit.setResultTransformer(Transformers.aliasToBean(EmailDataBean.class));
Alternatively, instead of using Projections, you can use
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
but this will not fetch distinct rows from the database but rather have Hibernate filter the results (removing the duplicates).

Related

How to get First 5 elements Hibernate

I have a very long object, so to make the system faster, I decided to show only the top 5 on "attendance" attribute (insted to show all the elements) when retrieve by the "get" service.
I have a attendances list, but there is a way to say only get the top 5 (on the list get) and when I got the results from the "detail" service, I will have all the itens.
#ManyToMany
private List<Attendance> attendance;
Write a custom repostitory, inject the entitymanager and use a query like that:
entityManager.createQuery("Select a from Enity e join e.attendence a")
.setMaxResults(5)
.getResultList();
Even you can do by Hibernate Criteria:
public List findByLimit(Class persistentClass, String orderproperty, int limit)
{
Session session = getSession(); // Get Session here
try
{
Criteria criteria = session.createCriteria(persistentClass);
criteria.addOrder(Order.desc(orderproperty));
criteria.setMaxResults(limit);
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return criteria.list();
}
catch (RuntimeException re)
{
//Catch exception
}
finally
{
//close the session
}
}
Now call the above function :
findByLimit(Example.class,id,5); // here id is your order property

Use Criteria to select a particular field from DB?

I have a method like below
public List<String> getSimilarResourceNames(String resourceName){
String searchString = "%"+resourceName+"%";
Session session = getSession();
Criteria criteria = session.createCriteria(Resource.class);
criteria.add(Restrictions.like("name", searchString));
return criteria.list()
}
This will return me the entire resource from the DB, but what i need is just the name of the resource. How can I accomplish that ?
Use Projection, you can find examples in Hibernate documentation.
Criteria criteria = session.createCriteria(Resource.class);
criteria.setProjection(Property.forName("name"))
criteria.add(Restrictions.like("name", searchString));
By using Projection you will get other fields (Which you did not got by Projection) in your Pojo setted to default values. In HQL you can get specified column values as follow:
Query query = session.createQuery("select u.fullname from Users u");
List<Object[]> rows = query.list();
List<String> fullnames = new ArrayList<String>();
for (Object[] row: rows) {
fullnames.add(row[0]);
}
I hope this will help you.

How to query a database using Hibernate?

I understand some might simply answer this question with "Why didn't you just Google it"... But I did, and the more I researched this the more confused I got. I'm trying to query my database with Hibernate, the query has a 'where' clause.
Now creating a database entry is easy enough, in the case where I have a 'User' class, I simply do this:
// Gets a new session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
// Creates a new User object
User user = new User("John", "p#55w0rd*", "john#doe.com");
// Save and commit
session.save(user);
session.getTransaction().commit();
But what do I do when I what to for instance
select * from Users where id = '3';
My Google searches pointed to something called HQL, which makes me wonder why I couldn't of just used straight JDBC then. Also it doesn't seem very object oriented. And then there's something like
session.createCriteria(.......
But I'm not sure how to use this.. Any help? Thanks guys.
When you use Native Query (non HQL ) you need to tell hibernate explicitely to handle it like below :
In below query createSQLQuery is special function to handle native sql's
String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(User.class);
query.setParameter("employee_id", 3);
List<User> results = query.list();
This can be done using criteria as well for that following is good starting point:
Criteria criteria = sess.createCriteria( User.class);
List<User> users= criteria.list();
http://www.developerhelpway.com/framework/hibernate/criteria/index.php
First of all, you need a hibernate.cfg.xml which contains properties for hibernate. This is e.g url, username and password, the driver and dialect. This file is placed in a package called resources.
You have to choose between using Hibernate Annotations example
or using hbm.xml files example
This is how you tell hibernate what your database is like. It wil automatically create queries for you based on how you annotates or defines in e.g user.hbm.xml.
Create a HibernateUtil.java class which holds the session factory.
You can fetch data from the database with
Criteria crit = getSessionFactory().getCurrentSession().createCriteria(User.class);
Example using queries:
List<?> hibTuppleResultList = currentSession.createQuery(
"from Person p, Employment e "
+ "where e.orgno like ? and p.ssn = e.ssn and p"
+ ".bankno = ?")
.setString(0, orgNo).setString(1, bankNo).list();
for (Object aHibTuppleResultList : hibTuppleResultList)
{
Object[] tuple = (Object[]) aHibTuppleResultList;
Person person = (Person) tuple[0];
hibList.add(person);
}
In the end all I really wanted was to know that if you don't want to use HQL you get something called 'Criteria Queries', and that in my case I'd do something like this:
Criteria cr = session.createCriteria(User);
cr.add(Restrictions.eq("id", 3));
List results = cr.list();
Me: "Thanks!"
Me: "No problem :)"
PS - we can really delete this question.
Query q = session.createQuery("from User as u where u.id = :u.id");
q.setString("id", "3");
List result = q.list();
Query with Criteria:
Criteria cr = session.createCriteria(User.class);
List results = cr.list();
Restrictions with Criteria:
Criteria cr = session.createCriteria(User.class);
cr.add(Restrictions.eq("id", 3));
// You can add as many as Restrictions as per your requirement
List results = cr.list();
You could also use it like this
List results = session.createCriteria(User.class).add(Restrictions.eq("id", 3)).list();
Some example for Crieteria Rsetriction query
Criteria cr = session.createCriteria(Employee.class);
// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));
// To get records having salary less than 2000
cr.add(Restrictions.lt("salary", 2000));
// To get records having fistName starting with zara cr.add(Restrictions.like("firstName", "zara%"));
// Case sensitive form of the above restriction.
cr.add(Restrictions.ilike("firstName", "zara%"));
// To get records having salary in between 1000 and 2000
cr.add(Restrictions.between("salary", 1000, 2000));
// To check if the given property is null
cr.add(Restrictions.isNull("salary"));
// To check if the given property is not null
cr.add(Restrictions.isNotNull("salary"));
// To check if the given property is empty
cr.add(Restrictions.isEmpty("salary"));
// To check if the given property is not empty
cr.add(Restrictions.isNotEmpty("salary"));
You can create AND or OR conditions using LogicalExpression restrictions as follows:
Criteria cr = session.createCriteria(Employee.class);
Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");
// To get records matching with OR condistions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );
// To get records matching with AND condistions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );
List results = cr.list();
I think this will help you

Left join using hibernate criteria

I have two entity: Issue and Issue_Tracker. I am using Hibernate 3.6.
SELECT `issues`.`issue_id`,
`issues`.`issue_raised_date`,
`issues`.`issue_description`,
`issue_tracker`.`tracker_status`
FROM `issues`
LEFT JOIN `issue_tracker` ON `issues`.`issue_id` = `issue_tracker`.`issue_id`
WHERE `issues`.`status`="Escalate To"
How to achieve this using Hibernate Criteria, and most Important, I have to use it for pagination.
and My Dao is as follows to show the list of Issues in jqgrid
public List showHelpDeskIssues(DetachedCriteria dc, int from,
int size) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
try
{
Criteria criteria = dc.getExecutableCriteria(session);
criteria.setFirstResult(from);
criteria.setMaxResults(size);
criteria.add(Restrictions.eq("status","Escalate To"));
return criteria.list();
}
catch (HibernateException e)
{
e.printStackTrace();
throw e;
} }
For brief explanation please refer this question how to show two tables data in jqgrid using struts2 - jqgrid plugin and hibernate
any help would be great.
you can try the following
Criteria criteria = session.createCriteria(Issues.class);
criteria.setFirstResult(from);
criteria.setMaxResults(size);
criteria.setFetchMode('parent.child', FetchMode.JOIN);
criteria.add(Restrictions.eq("status", "Escalate To"));
List<Issues> list= criteria.list();
here parent is the property name in Issues.java and child is the property in IssueTracker.java.
Well,
follow one sample...
Criteria crit = session.createCriteria(Issues.class);
crit.createAlias("otherClass", "otherClass");
crit.add(Restrictions.eq("otherClass.status", "Escalate To"));
List result = crit.list();
I think so this can to help!!
Try this out because this worked for me
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Issues.class, "issues");
criteria.setFetchMode("issues.issuetracker", FetchMode.JOIN);
criteria.createAlias("issues.issuetracker", "issuetracker");
criteria.add(Restrictions.eq("status","Escalate To"));
List list = criteria.list();
return list;
Note: In Hibernate criteria, inner outer join and inner join are one and the same. Do not get confused.
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
try{
Criteria criteria = session.createCriteria(Issues.class, "issues");
criteria.setFirstResult(from);
criteria.setMaxResults(size);
criteria.createAlias("issues.issuestracker", "issuestracker", JoinType.LEFT_OUTER_JOIN);
criteria.add(Restrictions.eq("issues.status", "Escalate To"));
return criteria.list();
}catch(HibernateException e){
e.printStackTrace();
throw e;
}
This should solve your issue. Let me know if you face any trouble.

How do I stop hibernate returning multiple instances when using "join" fetch mode?

Given the following I am trying to force the child collection (countryData) to be loaded when I perform the query, this works however I end up with duplicates of the Bin records loaded.
public Collection<Bin> getBinsByPromotion(String season, String promotion) {
final Session session = sessionFactory.getCurrentSession();
try {
session.beginTransaction();
return (List<Bin>) session.createCriteria(Bin.class).
setFetchMode("countryData", FetchMode.JOIN).
add(Restrictions.eq("key.seasonCode", season)).
add(Restrictions.eq("key.promotionCode", promotion)).
add(Restrictions.ne("status", "closed")).
list();
} finally {
session.getTransaction().commit();
}
}
I don't want the default (lazy) behavior as the query will return ~8k records thus sending 16k additional queries off to get the child records.
If nothing else I'd prefer.
select ... from bins b where b.seasonCode = ?
and b.promotionCode = ?
and b.status <> 'Closed';
select ... from binCountry bc where bc.seasonCode = ?
and bc.promotionCode = ?;
you can use CriteriaSpecification.DISTINCT_ROOT_ENTITY;
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

Categories

Resources