Update with Join hibernate (HQL) - java

I'm on trouble with an hql problem.
I would like to write a query, that updates an attribut, and that's based on a value on another table.
This is my example, I have those two tables : Client and Widhdrawal.
Client : idClient, name ...
Widhdrawal : idWidh, cost, and the idClient (foreign key)
Now if i would update the client, under the condition of (idClient = 5 for example), i can't.
I tried this, but in vain :
String hql = "UPDATE Widhdrawal W set W.cost = :salary " +
"where W.Client.id_client = :employee_id)";
Query query = session.createQuery(hql);
query.setParameter("salary", 1000);
query.setParameter("employee_id", 5);
int result = query.executeUpdate();
I hope that someone can have some advices, thank you.

Try this:
String hql = "UPDATE Widhdrawal W set W.cost = :salary " +
"where W.idClient = :employee_id)";

Thank you, i found the solution.
I hope that this can help other people ...
This problem is du to lowerCase.
String hql = "UPDATE Widhdrawal W set W.cost= :newCost " +
"where W.client.id_client = :id_cl";
Query query = session.createQuery(hql);

Try this way --
String hql = "UPDATE Widhdrawal W set W.cost = :salary " +
"where W.id_client =(select id_client from client where id_client = :employee_id)";
Widhdrawal and client is POJO class name.

Related

Filter rows in DataSet using JPA/Hibernate

I have the following code which is used to retrieve data from multiple tables (using joins) and then mapping every row into a DTOList but I also need to apply filters based on user preferences: per table1.name or table2.name, table3, etc.
So I just want to know what would be the best way to do it in terms of performance and best practices;
retrieving all rows and then apply the filters with lambdas (easier)
change the query to a dynamic query with Criteria or something else?
Any other solution=?
#Repository
public class ArchiveRepository {
#Autowired
EntityManager em;
String queryStr = "select wsr.id as sampleid, s.id as slideid, tb.name as batchname, k.lot_number as kitlot, " +
" 'STRING' as slidetype, tb.worklist_name as worklist, wsr.final_call as results, " +
" wa.final_pattern_ids as patterns, 'edited/yesno' as edited, wsr.last_modified_by as user, wsr.last_modified_date as time " +
" from slide s " +
" left join table2 tb on s.test_batch_id = tb.id " +
" left join table3 k on tb.kit_lot_id = k.id " +
" left join table4 w on s.id = w.slide_id " +
" left join tabl5 pw on pw.well_id = w.id " +
" left join tabl6 cw on cw.well_id = w.id " +
" left join tabl7 wsr on wsr.patient_well_sample_id = pw.id or wsr.control_sample_id = cw.id " +
" left join (select * from *** (other subselect)) wa on wa.well_sample_id = wsr.**id or wa.well_sample_id = wsr.**id " +
"where tb.state = 'STATENEEDED'";
public ArchiveDataListDTO getArchiveData(){
Query query = em.createNativeQuery(queryStr);
ArchiveDataListDTO archiveDataListDTO = new ArchiveDataListDTO();
List<Object[]> resultL = (List<Object[]>)query.getResultList();
for( Object[] o : resultL){
archiveDataListDTO.addArchiveDataRow(
new ArchiveDataDTO((String)o[0], String.valueOf(o[1]), (String) o[2], (String) o[3], (String) o[4], (String) o[5],
(String) o[6], (String) o[7], (String) o[8], (String) o[9], (String) o[10]));
}
return archiveDataListDTO;
}
}
**
note I struggled some with the code cause I wanted to apply #sqlresultsetmapping to avoid manual results mapping but it just didn´t work, most of the examples out there are when you have an entity in the DB but in this case I retrieve from many tables.**
Thanks so much
2 .- change the query to a dynamic query with Criteria or something else?
I ended up creating the query on the fly; depending on the filters I get from UI i assemble the query with Java and send it to DB, it´s easier since this required many tables...

Hibernate Group By Query

Please help me understand whats wrong with this query.
String sql = "select d.arc_alrt_cde, d.alrt_desc, count(d.arc_alrt_cde) " +
"from arc_alrt a, arc_alrt_def d " +
"where d.arc_alrt_cde = a.alrt_cde " +
"and (a.stat_cde = 'OPEN' or a.stat_cde = 'RE-OPENED') " +
"group by d.arc_alrt_cde, d.alrt_desc "+
"order by count(d.arc_alrt_cde) desc"
println sql
Query query = session.createQuery(sql);
Printing SQL
sql = select d.arc_alrt_cde, d.alrt_desc, count(d.arc_alrt_cde) from arc_alrt a, arc_alrt_def d where d.arc_alrt_cde = a.alrt_cde and (a.stat_cde = 'OPEN' or a.stat_cde = 'RE-OPENED') group by d.arc_alrt_cde, d.alrt_desc order by count(d.arc_alrt_cde) desc
Getting the following error. Tried IN clause also.. Not working..
Error:
java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.hql.internal.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:64)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:300)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:203)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:126)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:88)
That's an SQL query not a HQL one, so you should use:
SQLQuery query = session.createSQLQuery(sql);
That exception you got is thrown because Hibernate expects an HQL query but receives an SQL query instead.
You are to name the count field such as count(d.arc_alrt_cde) as countOfXXX
and also your entity should be aligned with that query or you should remove that count field at all.
Changed it to use object properties and it worked. Thanks for your inputs.
String sql = "select alert.alertCode, def.alertDesc, count(alert.alertCode) " +
"from ArcAlert as alert, ArcAlertDef as def " +
"where alert.alertCode = def.alertCode " +
"and alert.status in ('OPEN', 'RE-OPENED') " +
"and alert.assignedTo = '"+assignedTo+"' " +
"group by alert.alertCode, def.alertDesc " +
"order by count(alert.alertCode) desc"
Query query = session.createQuery(sql);
lst = query.list()

HQL: variable column

I'm able to set variable values for "where" restrictives:
Query criteria = session.createQuery(
"select test.col1, test.col2, test.col3
"from Test test " +
"where test.col = :variableValue ");
criteria.setInteger("variableValue", 10);
But is it possible to set variable column like this?
String variableColumn = "test.col1";
Query criteria = session.createQuery(
"select test.col1, test.col2, test.col3
"from Test test " +
"where :variableColumn = :variableValue ");
criteria.setInteger("variableValue", 10);
criteria.setString("variableColumn", variableColumn);
This is the result:
Exception in thread "main" Hibernate: select .... where ?=? ...
org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
...
at _test.TestCriteria.main(TestCriteria.java:44)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting the nvarchar value 'test.col1' to data type int.
...
UPDATE (working solution):
Query criteria = session.createQuery(
"select test.col1, test.col2, test.col3
"from Test test " +
"where (:value1 is null OR test.col1 = :value1) AND
(:value2 is null OR test.col2 = :value2) "
Does this make sense in your application:
String query = "select test.col1, test.col2, test.col3" +
"from Test test " +
"where {columnName} = :variableValue ";
Object variableValue = // retrieve from somewhere
String columnName = // another retrieve from somewhere
query = query.replace("{columnName}", columName);
// Now continue as always
This is generally a naive query constructor. You may need to refactor this idea to a separate utility/entity-based class to refine (e.g. SQL injection) the queries before execution.
You can set the column name as part of the string. For security you may do the SQL escaping manually, but at the end you can achieve this.
To avoid SQL injection you can use commons class:
String escapedVariableColumn = org.apache.commons.lang.StringEscapeUtils.escapeSql(variableColumn);
Query criteria = session.createQuery(
"select test.col1, test.col2, test.col3
"from Test test " +
"where " + escapedVariableColumn + " = :variableValue ");
criteria.setInteger("variableValue", 10);

More elegant way to write a hibernate query

Can someone help me write a better code. I tried this but its not working :
Query query = session.createQuery("from MyTable order by :sortvariable :sortorder");
query.setParameter("sortvariable", sortvar);
query.setParameter("sortorder", order);
This is not working as well
Query query = session.createQuery("from MyTable table order by table." + sortvar + " " + " :sortorder");
query.setParameter("sortorder", order);
I managet to get it working with this :
Query query = session.createQuery("from MyTable table order by table." + sortvar + " " + order);
I need to do this with query because I'm using setMaxResults() and setFirstResult().
I don't think you can use parameters to identify keywords that way. Is it possible to do what you're trying to do using the criteria API?
boolean sortAscending = ...;
Criteria criteria = session.createCriteria(MyTable.class);
criteria.addOrder(sortAscending? Order.asc(sortVar): Order.desc(sortVar));

How can I execute an update (named query) in Hibernate Template?

I have a namedQuery like this:
#NamedQueries ({ ...
#NamedQuery(name = "myUpdate", query = "update User set country = 'EN' where user.id = :id")
...
})
In dao layer
getHibernateTemplate().bulkUpdate(...?)
UPDATE
Query query = sessionFactory.getCurrentSession.getNamedQuery("myUpdate");
getHibernateTemplate.bulkUpdate(query.getQueryString(), id);
I get an error:
Hibernate: update User, set country=EN where id = 2343 ORA-00971: missing SET keyword
Anybody now how can resolve this problem?
UPDATE 2
#NamedQuery(name = "myUpdate", query =
"update User set country = 'EN' where
user.profile.id = ?")
OK
#NamedQuery(name = "myUpdate", query =
"update User set country = 'EN' where
user.profile.name = ?")
NOT OK :(
Unfortunately, that feature is missing in spring, as the named queries are supposed to be used only to retrieve data. One thing you can do is (this is a bit of a work around)
Session session = getHibernateTemplate().getSession();
Query query = session.getNamedQuery("myUpdate");
String update = query.getQueryString();
getHibernateTemplate().bulkUpdate(update, [params]);
I would put that in some kind of helper, so your DAO logic doesn't have to go around spring too.
edit
there's a dangling comma between User and set "update User , set country=EN where"
Actually this is a very old question but I had the same problem today. I realized that the update does not work since you cannont have a join inside of a simple UPDATE. That is also the reason why the comma is added. Hibernate tries to rewrite the query like this:
UPDATE User u, Profile p SET u.country = 'EN' where p.name = ? AND p.id = u.profile.id
To solve the issue you need to select the ids from the second table yourself.
#NamedQuery(name = "myUpdate", query = ""
+ " UPDATE User u "
+ " SET country = 'EN' "
+ " WHERE u.profile.id IN ( "
+ " SELECT p.id "
+ " FROM Profile p "
+ " WHERE p.name = ? "
+ " )"

Categories

Resources