Hibernate updation not working - java

I am using following method to update data in database.
String hql = "UPDATE EmployeeSalary set salary = :sl,"
+ "monthYr=:dt "
+ "WHERE id =:id and client.id=:cid";
for (EmployeeSalary e : eList) {
Query query = session.createQuery(hql);
query.setParameter("sl", e.getSalary());
query.setParameter("dt", e.getMonthYr());
query.setParameter("id", e.getId());
query.setParameter("cid", e.getClient().getId());
int result = query.executeUpdate();
System.out.println("result is " + result);
if (eAttList.size() % 20 == 0) {
session.flush();
session.clear();
}
}
Is there any problem with code.
On execution it is showing
result is 0
How to resolve above problem.

The documentation about update queries says:
No "Forms of join syntax", either implicit or explicit, can be specified in a bulk HQL query. Sub-queries can be used in the where-clause, where the subqueries themselves may contain joins.
Your query seems to violate this rule: client.id=:cid is an implicit join to the client entity.
Note that you're making your life difficult. You could simply get the entity by ID from the session (using Session.get()), and update it. Update queries are useful to update many rows at once.

Related

Update/delete queries cannot be typed

I want to implement update query in JPA. I tried this:
public void updateTransactionStatus(String uniqueId, String type, String status) throws Exception {
String hql = "update " + PaymentTransactions.class.getName()
+ " e SET e.status = :status WHERE e.unique_id = :unique_id AND e.type = :type";
TypedQuery<PaymentTransactions> query = entityManager.createQuery(hql, PaymentTransactions.class).setParameter("status", status).setParameter("unique_id", uniqueId).setParameter("type", type);
query.executeUpdate();
}
But I get Update/delete queries cannot be typed. What is the proper wya to implement this?> I tried to replace TypedQuery with Query but I get The type Query is not generic; it cannot be parameterized with arguments <PaymentTransactions>
In general if you do not need to you should avoid using batch updates with JPA unless they are triggered from within a REQUIRES_NEW marked transaction (and thats the only operation).
It seems that you need to perform an update on one unique entry so I would suggest a query followed by a modification, thats it:
// retrieve
PaymentTransactions paymentTransaction =
entityManager.createQuery("select t from " + PaymentTransactions.class.getName()
+ " where e.unique_id = :unique_id AND e.type = :type "
, PaymentTransactions.class);
.setParameter("unique_id", uniqueId).setParameter("type", type)
.getSingleResult();
// modify
paymentTransaction.setStatus(status);
Here is the place for a TypedQuery.
As long as your method is within a transactional context, thats all you need to do to update the entry.

JPA EntityManager updates object before transaction has finished? [duplicate]

I have native query to run :
String sqlSelect =
"select r.id_roster as id, " +
"count(roster_cat.id_category), " +
" sum(case when roster_cat.id_category IN ( :categoryIds) then 1 else 0 end) as counter " +
"from roster r " +
"inner join roster_sa_categories roster_cat " +
"on r.id_roster = roster_cat.id_roster " +
"where r.day = :dayToLookFor " +
"and r.id_shop = :idShop " +
"group by r.id_roster " +
"having count(roster_cat.id_category) = :nrCategories " +
"and count(roster_cat.id_category) = counter" ;
Query selectRostersQuery = entityManager.createNativeQuery(sqlSelect);
selectRostersQuery.setParameter("categoryIds", Arrays.asList(categoryIds));
selectRostersQuery.setParameter("dayToLookFor", day.toString());
selectRostersQuery.setParameter("idShop", shopId);
selectRostersQuery.setParameter("nrCategories", categoryIds.length);
List<Integer> rosterIds = new ArrayList<>();
List<Object> result = (List<Object>) selectRostersQuery.getResultList();
For some reason Hibernate choses to do an update before executing the select and it is really interfering with my data
Hibernate: /* update domain.Roster */ update roster set day=?, employee_count=?, interval_end=?, interval_start=?, id_shop=? where id_roster=?
Hibernate: /* update Roster */ update roster set day=?, employee_count=?, interval_end=?, interval_start=?, id_shop=? where id_roster=?
Hibernate: /* dynamic native SQL query */ select r.id_roster as id, count(roster_cat.id_category),sum(case when roster_cat.id_category IN ( ?) then 1 else 0 end) as counter from roster r inner join roster_sa_categories
roster_cat on r.id_roster = roster_cat.id_roster where r.day = ? and r.id_shop = ? group by r.id_roster having count(roster_cat.id_category) = ? and count(roster_cat.id_category) = counter
Any help would be appreciated,Thank you
What you describe is precisely what Hibernate's FlushMode.AUTO implies.
Any modifications in the Persistence Context (1LC) at the time a query is executed will be automatically flushed prior to executing the query, guaranteeing that the results returned by the database match that which was cached by in-memory modifications.
If the query is going to return entities that you're seeing the update for, then you should likely re-evaluate your operations, making sure that the query fires prior to the update to avoid the flush operation, which can be quite expensive depending on the volume of entities in your Persistence Context.
If you are absolutely sure that the changes you're seeing flushed won't be returned by the query in question, you can always force the query not to cause a flush by setting the flush mode manually:
Query query = session.createQuery( ... );
query.setFlushMode( FlushMode.COMMIT );
List results = query.list();
But only do this if you're sure that the query wouldn't then be reading uncommitted changes as this can cause lots of problems and lead to long debug sessions to understand why changes are being inadvertantly lost by your application.

sql to hql throwing exception

I'm using hibernate in my project and I'm trying to convert an existing sql query from DaoImplementation class to hql,
The sql query I have is
JdbcTemplate select = new JdbcTemplate(dataSource);
String sql = "SELECT * FROM (SELECT site_id,rtc,sigplan,cycle_time,health,phase_no,phase_time,active_groups,groupscolour,ip "+
"FROM status_data where rtc>='" + fromDate + "' and rtc<'" + toDate + "' and "+
"site_id=" + SiteId + " order by rtc desc limit "+recordLimit+" )as temp ORDER BY RTC ASC";
I wrote the hql version to get data from HealthLog table as
String hql = " select f from (select h from HealthLog h where rtc>='"+fromDate+"' and rtc <'"+toDate+"' "
+ "and siteId = "+siteId+" order by rtc desc limit "+limit+" ) as f order by rtc asc ";
return super.readListByHql(hql);
But the above hql throws the following exception
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 16 [ select f from (select h from com.traff.hibernate.model.HealthLog as h where rtc>='1974-08-01 14:10:00.0' and rtc <'1974-09-01 23:46:20.6' and siteId = 20 order by rtc desc limit 50000 ) as f order by rtc asc ]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:79)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:276)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:180)
at org.hibernate.hql.intern
I also tried the below code snippet but that giving me wrong results
Criteria criteria = createEntityCriteria();
criteria.add(Restrictions.ge("rtc", fromDate));
criteria.add(Restrictions.lt("rtc", toDate));
criteria.add(Restrictions.eq("siteId", siteId));
criteria.setMaxResults(limit);
criteria.addOrder(Order.asc("rtc"));
criteria2 = criteria;
criteria2.addOrder(Order.desc("rtc"));
return criteria2.list();
Which is the correct way to achieve the result?
First of all, as already mentioned in the comments, you cannot do a subquery within the FROM clause in HQL.
See: Hibernate Documentation
Secondly, the limit keyword is not supported by HQL.
Usually you would use query.setFirstResult(0) and query.setMaxResults(recordLimit) methods where query has the type of the Query Interface. But since you are using the limit in a subquery, there is no way.
See: How to set a limit to inner query in Hibernate?
Some options:
Use a native SQLQuery
Since you are only sorting in the outer Query. You could only execute the inner query and sort in Java.
Example for Option 2:
Session session = factory.openSession();
Query query = session
.createQuery("FROM HealthLog "
+ "WHERE rtc >= :rtcL and rtc < :rtcG and siteId = :siteId "
+ "ORDER BY rtc DESC");
query.setParameter("rtcL", fromDate);
query.setParameter("rtcG", toDate);
query.setParameter("siteId", siteId);
query.setFirstResult(0);
query.setMaxResults(recordLimit);
List<HealthLog> res = query.list();
session.close();
Collections.sort(res, new Comparator<HealthLog>() {
public int compare(HealthLog o1, HealthLog o2) {
return o1.getRtc().compareTo(o2.getRtc());
}
});
The query above returns HealthLogs with all attributes. If you want to only retrieve specific attributes, you can add a SELECT new HealthLog(siteId,rtc,sigplan,cycle_time,...) to your Query with a fitting constructor in HealthLog.
Please note that the code snippet might not be ready to use, since i do not know your model and attribute names.

Hibernate Criteria with joins not generating correct SQL

I'm trying to execute a Criteria query but when I execute the code, the SQL only brings up company_synonym in the from clause, not the other two.
The mappings are:
Company has 1-to-Many CompanySynonyms
Company has 1-to-Many CompanyProductRoles
I want the query to return CompanySynonym objects, so I tried this:
Criteria criteria = session.createCriteria(CompanySynonym.class, "cs")
.createAlias("cs." + CompanySynonym.COMPANY, "cmp")
.createAlias("cmp." + Company.COMPANY_PRODUCT_ROLE, "cpr")
.add(Restrictions.eq("cs." + CompanySynonym.TYPE, "1234"))
.add(Restrictions.eq("cpr." + CompanyProductRole.PRODUCT_ID, Integer.valueOf(productId)))
.add(Restrictions.isNotNull("cpr." + CompanySynonym.Company_ID))
.add(Restrictions.eq("cpr." + CompanyProductRole.ROLE_CODE, "AB"));
And it generates this SQL:
select this_.company_syn_id_i as company1_0_0_, this_.company_id_i as company5_0_0_, this_.cmp_syn_end_d as cmp2_0_0_, this_.cmp_syn_type_cd_c as cmp3_0_0_, this_.cmp_syn_c as cmp4_0_0_
from product.dbo.company_synonym this_
where this_.cmp_syn_type_cd_c=?
and cpr1_.product_id_i=?
and cpr1_.company_id_i is not null
and cpr1_.role_cd_c=c
What am I missing or doing wrong here?

Setting ORDER BY and LIMIT clause on JPA Query

I'm very, very new to Hibernate and JPA. I want to be able to apply ORDER BY and LIMIT clauses to a Hibernate(?) query, but am coming up empty. NOTE: I inherited this code.
Here is the current code:
public SomeCoolResponse getSomeCoolResponse(String myId) {
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id";
Query q = getEntityManager().createQuery(queryString);
q.setParameter("id", myId);
List<MyThings> list = q.getResultList();
if(list.size() > 0) {
return list.get(0);
}
return null;
}
Instead of getting an entire list and then just returning the first result (which is the only one we need), I'd like to be able to apply a LIMIT 0,1 clause so that the query will be faster. Also, the query needs to be sorted descending on aThing.created which is a UNIX timestamp integer.
I've tried altering queryString like this:
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id ORDER BY aThing.created LIMIT 0,1";
But Hibernate still returns the entire set.
I've looked at using the JPA CriteriaBuilder API, but it hurt my brain.
I'm a total n00b when it comes to this, and any help is greatly appreciated!
I think you need
q.setMaxResults(1);
See also the accepted answer here.
How do you do a limit query in HQL?
As to the "order by" clause you may include it in the queryString.
The JPQL equivalent to LIMIT start,max is:
setFirstResult and setMaxResults:
q.setFirstResult(start);
q.setMaxResults(limit);

Categories

Resources