how to add Hibernate "createAlias" Child Restriction to parent Entity Restriction - java

I've got a requirment where I need to apply a search keyword to name and and state of Parent entity (Customer) and also name attribute of child entity Order.
List<Criterion> aliasRestrictionsCriterion = new ArrayList<Criterion>();
Junction quotedLikeRestrictions = Restrictions.disjunction();
quotedLikeRestrictions.add(Restrictions.ilike("customerName", token, MatchMode.ANYWHERE));
quotedLikeRestrictions.add(Restrictions.ilike("customerState", token, MatchMode.ANYWHERE));
restrictions.add(quotedLikeRestrictions);
and to include the child table in the query I'm am doing the following
Criteria alias = criteria.createAlias("order", "order")
.add(Restrictions.ilike("order.name", token, MatchMode.ANYWHERE));
Hibernate is generating the following query but what I need is to have order.name like comparison get added to the parent block.
CUSTOMER this_ inner join ORDER order_ on this_.ORDER_ID=order_.ORDER_ID where
(lcase(this_.name) like ? or lcase(this_.state) like ?) and (lcase(order_.NAME)
like ?)
what I want is to have (lcase(order_.NAME) like ?) inside the parent block. So I want is the following
(lcase(this_.name) like ? or lcase(this_.state) like ? or lcase(order_.NAME) like ?)
How can I achieve this ?
Update: this is how I'm calling the criteria
protected List getEntities(List<Criterion> restrictions, String aliasSearchToken) {
Session session = currentSession();
Criteria criteria = session.createCriteria(getEntityClass());
// apply restrictions.
if (restrictions != null) {
for (Criterion criterion : restrictions) {
criteria.add(criterion);
}
}
Criteria alias = criteria.createAlias("order", "order").add(Restrictions.ilike("order.name", searchToken, MatchMode.ANYWHERE));
List list = criteria.list();
if (list != null) {
return list;
}
return Collections.emptyList();
}
Update 2:
protected List getEntities(List<Criterion> restrictions, String aliasSearchToken) {
Session session = currentSession();
Criteria criteria = session.createCriteria(getEntityClass());
Junction or = Restrictions.disjunction();
or.add(Restrictions.ilike("order.name", searchToken, MatchMode.ANYWHERE));
criteria.createAlias("order", "order").add(or);
// apply restrictions.
if (restrictions != null) {
for (Criterion criterion : restrictions) {
criteria.add(criterion);
}
}
List list = criteria.list();
if (list != null) {
return list;
}
return Collections.emptyList();
}
produced
select ....... from CUSTOMER this_ inner join ORDER order_ on this_.ORDER_ID=order_.uid where (lcase(order_.NAME) like ?) and (lcase(this_.name) like ? or lcase(this_.state) like ?)
the orderName is just before but still not in the second or statement ... I'm so confused.

Well, instea of adding the restriction to the Criteria (which creates an AND), you must add it to the quotedLikeRestrictions disjunction:
quotedLikeRestrictions.add(Restrictions.ilike("order.name", token, MatchMode.ANYWHERE));

Related

Joining multiple table using hibernate criteria

I am trying to join multiple table to join using criteria but getting some problem , please help me:
I have a sql query like :
SELECT a.type, a.time, c.code AS exchangeCode
FROM CutOffTime AS a INNER JOIN
Country AS b ON a.country_fk = b.id INNER JOIN
Exchange AS c ON c.country_fk = b.id
These three table : CutOffTime (has country), Country, Exchange (has country) are 3 entity classes.
How can i join like this using hibernate criteria,my code below still not complete :
List<Map<String, Object>> aa= ( List<Map<String, Object>>) getHibernateTemplate().executeFind(new HibernateCallback() {
#Override
public Object doInHibernate(final Session session) throws HibernateException, SQLException {
final Criteria c = session.createCriteria(CutOffTime.class,"cutofftime");
c.createAlias("cutofftime.country", "country");
final Criteria c2= session.createCriteria(Exchange.class,"exchange");
c2.createAlias("exchange.country", "country");
// c.add(Restrictions.eqProperty("cutofftime.country.id","exchange.country.id"));
return c.list();
}
});
I think you can't get it done from hibernate using a single join as you don't have a bidirectional relationship from Country to anywhere.So I think you have to have 2 seperate joins and then filter the results in second join such that the countrrID in (country ids in first join)

Hibernate get List from database

In the following code I am trying to get a List of Products which contains all the products in the database:
public List<Products> getAllProducts() throws Exception{
try{
List<Products> products ;
org.hibernate.Transaction tx = session.beginTransaction();
products = session.createSQLQuery("SELECT * FROM Products").list();
if(products.size() > 0)
{
return products;
}
return null;
}
catch(Exception e)
{
throw e;
}
}
however this exception is thrown:
[Ljava.lang.Object; cannot be cast to mediatek.Products
List<Products> list = session.createCriteria(Products.class).list();
This will give you all the records of products table from database
Your answer not only adds a cast, but switches from SQL to HQL. Since your 2nd query is in HQL, Hibernate is able to use mapping information to know what class to return. This is the preferred way to do things in Hibernate, but if you had to use SQL for some reason you could achieve the same thing with:
(List<Products>)session.createSQLQuery("SELECT * FROM Products").addEntity(Products.class).list();
In Hibernate 5 the session.createCriteria methods are deprecated.
You will need to use a CriteriaBuilder and query from there to get a generic list of Products instead of just List.
Imports
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
Code
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Products> criteria = builder.createQuery(Products.class);
criteria.from(Products.class);
List<Products> products = session.createQuery(criteria).getResultList();
Forgot to type cast the query. it is working now.
List<Products> products = (List<Products>) session.createQuery("from Products").list();
For example you have code:
Session session = getSessionFactory().openSession();
Transaction transaction = null;
try {
SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM schema.yourtable WHERE param = :param");
sqlQuery.setString("param", "someParam");
And if your next step will be:
List list = sqlQuery.list();
You will receive list with Rows. You can see your Entity.class parameters in debug, but cat cast to List with your Entities:
List<Entity> list = (List<Entity>) sqlQuery.list();
In this point will be ClassCastException!
And if you need received List with your Entities you must add entity type to sql query:
List<Entity> list = (List<Entity>)sqlQuery.addEntity(Entity.class).list();
That's all. I hope someone will help.
if you using sql query, you should add this line at the last of the query to get the list you want:
.setResultTransformer(Transformers.aliasToBean(testDTO.class)).list();

criteria query ORDER BY yields error. Is this an SQL-SERVER limitation? How could I order by correctly on a complicated criteria query?

I have the following criteria query:
String cat = "H";
Criteria criteria = currentSession().createCriteria(this.getPersistentClass()).
add(Restrictions.ne("category", cat)).
createAlias("employees", "emp").
createAlias("emp.company", "company");
Disjunction disjunction = Restrictions.disjunction();
for(Region r: regions){
disjunction.add(Restrictions.eq("company.region", r));
}
criteria.add(disjunction);
if(status != null) {
criteria.add(Restrictions.eq("status", status));
}
if (period != null) {
criteria.add(Restrictions.eq("period", period));
}
criteria.setProjection(Projections.groupProperty("id")) //this line was added to try to "fix" the error, but it still happened.
criteria.addOrder(Order.asc("id"));
I guess a query that explains my criteria query could be:
select n.* from NOMINATION n
join NOMINEE i on n.NOM_ID = i.NOM_ID
join EMPLOYEE e on e.EMP_ID = i.EMP_ID
join COMPANY c on c.COMPANY_CODE = e.COMPANY_CODE
where n.CATEGORY_CODE!='H' and (c.REGION_ID = ? or c.REGION_ID = ? or c.REGION_ID = ?) and n.STATUS_ID = ? and n.PERIOD_ID = ?
order by n.NOM_ID
What I am trying to do here, is pretty confusing but for the most part it works except when I add this specific line (though the query works fine):
criteria.addOrder(Order.asc("id"));
and then I get error:
java.sql.SQLException: Column "NOMINATION.NOM_ID" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
Which I suspect is something that has to do with SQL-SERVER. I am already grouping by id. So what am I doing wrong here, or should I just use HQL?
Your current query seems to be a simple Query which doesn't have any group function used or not a group by query. According to your current requirements you do not have to use this line.
criteria.setProjection(Projections.groupProperty("id")).addOrder(Order.asc("id"));
Or you have to modify your sql statements.

JPA / Hibernate: CriteriaBuilder - How to create query using relationship object?

I have the following four tables:
SCHEDULE_REQUEST TABLE:
ID,
APPLICATION_ID (FK)
APPLICATION TABLE:
ID,
CODE
USER_APPLICATION TABLE:
APPLICATION_ID (FK),
USER_ID (FK)
USER TABLE:
ID,
NAME
Now I wanted to create a CriteriaBuilder where condition is to select ScheduleRequests for specified user Ids.
I have the following codes:
List<User> usersList = getSelectedUsers(); // userList contains users I wanted to select
CriteriaBuilder builder = getJpaTemplate().getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<ScheduleRequest> criteria = builder.createQuery(ScheduleRequest.class);
Root<ScheduleRequest> scheduleRequest = criteria.from(ScheduleRequest.class);
criteria = criteria.select(scheduleRequest);
ParameterExpression<User> usersIdsParam = null;
if (usersList != null) {
usersIdsParam = builder.parameter(User.class);
params.add(builder.equal(scheduleRequest.get("application.userApplications.user"), usersIdsParam));
}
criteria = criteria.where(params.toArray(new Predicate[0]));
TypedQuery<ScheduleRequest> query = getJpaTemplate().getEntityManagerFactory().createEntityManager().createQuery(criteria);
// Compile Time Error here:
// The method setParameter(Parameter<T>, T) in the type TypedQuery<ScheduleRequest> is not
// applicable for the arguments (ParameterExpression<User>, List<User>)
query.setParameter(usersIdsParam, usersList);
return query.getResultList();
Can you please help me how to pass query filter to a relationship object?
I think what I did in "application.userApplications.user" is wrong?
Please really need help.
Thank you in advance!
Using the canonical Metamodel and a couple of joins, it should work. Try if you get some hints from the following pseudo-code (not tested):
...
Predicate predicate = cb.disjunction();
if (usersList != null) {
ListJoin<ScheduleRequest, Application> applications = scheduleRequest.join(ScheduleRequest_.applications);
ListJoin<Application, UserApplication> userApplications = applications.join(Application_.userApplications);
Join<UserApplication, User> user = userApplications.join(UserApplication_.userId);
for (String userName : usersList) {
predicate = builder.or(predicate, builder.equal(user.get(User_.name), userName));
}
}
criteria.where(predicate);
...
In order to understand Criteria Queries, have a look at these tutorials:
http://www.ibm.com/developerworks/java/library/j-typesafejpa/
http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html
The second link should also guide you on how to use Metamodel classes, that should be built automatically by the compiler / IDE.

Hibernate = Column not found

I am running an aggregate function in java through hibernate and for some reason it is giving me this error:
INFO Binary:182 - could not read column value from result set: l_date; Column 'l_date' not found.
When I run the MySQL query the column names are l_date and logins and I can not figure out why it is not finding that.
I have tested the query in MySQL and verified that it does work. My function looks as follows.
public List<Logins> getUserLoginsByMonth() {
Session session = getSessionFactory().openSession();
ArrayList<Logins> loginList = null;
try {
String SQL_QUERY = "SELECT l_date as l_month, SUM(logins) as logins FROM (SELECT DATE_FORMAT(login_time, '%M') as l_date, COUNT(DISTINCT users) as logins FROM user_logins WHERE login_time > DATE_SUB(NOW(), INTERVAL 1 YEAR) GROUP BY DATE(login_time)) AS Z GROUP BY(l_month)";
Query query = session.createSQLQuery(SQL_QUERY);
List results = query.list();
for(ListIterator iter = results.listIterator(); iter.hasNext() ) {
Objects[] row = (Object[])iter.next();
System.out.println((Date)row[0}]);
System.out.println((BigInteger)row[1]);
}
}
catch(HibernateException e) {
throw new PersistenceDaoException(e);
}
finally {
session.close();
}
}
You need to add aliases as:
query.addScalar("l_month");
query.addScalar("logins");
and then call query.list();
It should work fine. addScalar is part of SqlQuery.

Categories