I'm learning JPA and doing some hands one with JPQL. I am having trouble in CASE expressions.
For example, this query,
Query caseQuery = em
.createQuery("SELECT t , CASE WHEN t.salary = 20000 THEN '20k' WHEN t.salary = 40000 THEN '40k' ELSE 'No salary' END FROM Teacher t");
and executing it using
List<Teacher> teachers = (List<Teacher>) caseQuery.getResultList();
but whenever I try to print the results out, I'm getting ClassCastException that Object cannot be converted to Teacher
I've tried using TypedQuery for Teacher but it didn't work. Could you experts please throw some light on executing this CASE statements in JPQL?
The reason is due to multiple select expressions in your query and not due to CASE Expression ,I believe with multiple select expressions the result will be Object[] rather than translated to the Entity. Some references JPA Tutorial ;JPQL. A related query already in stack overflow.
You should modify
List<Teacher> teachers = (List<Teacher>) caseQuery.getResultList();
to
List<Object[]> teachers = (List<Object[]>) caseQuery.getResultList();
where Object[] will be an array of Teacher& String
For TypedQuery also similar change should work.
Related
I'm trying to execute this query in my Java code, using Hibernate and Hibernate Spatial:
Query q = s.createQuery("SELECT c FROM crimes c WHERE ST_DWITHIN(ST_MakeLine(ARRAY['SRID=4326;POINT(-49.30621000000001 -25.515020000000003)','SRID=4326;POINT(-49.30619 -25.515770000000003)','SRID=4326;POINT(-49.306180000000005 -25.5162)','SRID=4326;POINT(-49.305780000000006 -25.5162)']), c.location, 0.0001) = true;");
But, this query causes an Exception:
e = (org.hibernate.hql.internal.ast.QuerySyntaxException) org.hibernate.hql.internal.ast.QuerySyntaxException: expecting CLOSE_BRACKET, found ',' near line 1, column 151 [SELECT c FROM com.safecity.server.db.model.EntityCrime c WHERE ST_DWITHIN(ST_MakeLine(ARRAY['SRID=4326;POINT(-49.305820000000004 -25.515330000000002)','SRID=4326;POINT(-49.306200000000004 -25.515340000000002)','SRID=4326;POINT(-49.30619 -25.515770000000003)','SRID=4326;POINT(-49.306180000000005 -25.5162)','SRID=4326;POINT(-49.305780000000006 -25.5162)']), c.location, 0.0001) = true]
I checked the query, and I cannot find the error. But, if I get this same query and execute on postgres console, the query is executed without any error and returns the correct value.
Please, someone can help me?
Thanks.
You are using native query here in hibernate. For this you have to use the query as below:
Query q = s.createSQLQuery("SELECT c FROM crimes c WHERE ST_DWITHIN(ST_MakeLine(ARRAY['SRID=4326;POINT(-49.30621000000001 -25.515020000000003)','SRID=4326;POINT(-49.30619 -25.515770000000003)','SRID=4326;POINT(-49.306180000000005 -25.5162)','SRID=4326;POINT(-49.305780000000006 -25.5162)']), c.location, 0.0001) = true;");
Use createSQLQuery() instead of createQuery(), if you want to create a db native query instead of HQL.
I solved this problem changing the query, for this one:
Query q = s.createQuery("SELECT c FROM crimes c WHERE ST_DWITHIN(ST_GeomFromText('LINESTRING(-49.305820000000004 -25.515330000000002,-49.306200000000004 -25.515340000000002,-49.30619 -25.515770000000003,-49.306180000000005 -25.5162,-49.305780000000006 -25.5162)', 4326), c.location, 0.0001) = true");
I don't know why, but it works.
Thanks for the help.
I have seen similar problems with ARRAY constructors in Hibernate before.
PostgreSQL: Issue with passing array to procedure
Replace with an array literal (and optionally a type cast) to make it work. A simple string literal will avoid various complications in the communication.
You are using the PostGis function ST_MakeLine() taking an array of geometry as input parameter.
geometry ST_MakeLine(geometry[] geoms_array)
So:
Query q = s.createQuery(
"SELECT c FROM crimes c
WHERE ST_DWITHIN(ST_MakeLine('{SRID=4326;POINT(-49.30621000000001 -25.515020000000003)
,SRID=4326;POINT(-49.30619 -25.515770000000003)
,SRID=4326;POINT(-49.306180000000005 -25.5162)
,SRID=4326;POINT(-49.305780000000006 -25.5162)}'::geometry[]), c.location, 0.0001)");
This would also explain why your alternative answer providing a linestring (as string literal!) works as well.
Also simplified the boolean expression in the WHERE clause like I commented. Appending = true is just noise.
In my Case after getting a certain list I need to to iterate that list to set some other fields of the POJO class.
if (transportHeaderList.get(i) instanceof TransportHeaderIiss){
transHeadIiss=(TransportHeaderIiss)transportHeaderList.get(i);
customerVendor= tOManagementDAO.getVendorCode(transHeadIiss.getCustVendUid());
}
if(customerVendor!=null){
transHeadIiss.setVendorCode(customerVendor.getCustVendCode());
}
The Above code calls getVendorCode method to get custVendorCode value from the database. The code for getVendorCode is as follows
public CustomerVendorIiss getVendorCode(Long custVendUid) {
List list=new ArrayList();
/* Criteria criteria = sessionFactory.getCurrentSession().createCriteria(CustomerVendorIiss.class);
criteria.add(Restrictions.eq("companyCode",user.getDefaultCompany().getCompanyCode()));
if(custVendUid!=null && custVendUid.intValue()>0)
{
criteria.add(Restrictions.eq("custVendUid",custVendUid));
}
list=criteria.list();*/
UsersIiss user= ApplicationContextProvider.getLoggedInUser();
String sqlQuery="select custVendCode as custVendCode from CustomerVendorIiss where companyCode ='"+ user.getDefaultCompany().getCompanyCode() +"' and custVendUid= "+custVendUid;
Query query = sessionFactory.getCurrentSession().createQuery(sqlQuery);
query.setResultTransformer(Transformers.aliasToBean(CustomerVendorIiss.class));
list=query.list();
if(list.size()>0){
return (CustomerVendorIiss)list.get(0);
}else{
return null;
}
}
When I executed above code with criteria, it took a lot time to get the values from table and set it to POJO class and sometimes I would get java.lang.OutOfMemoryError: Java heap space error . I guess that's because I am not de-allocating the criteria object.
when I executed the above code using createQuery() method I did not run into that issue and all that process of getting and setting was faster.
I want to understand what is that I am doing wrong here?
it would be great to know how and when criteria is better or HQL is better ?
Thank you !!
Actually these queries are different. The second one has an additional restriction
companyCode ='"+ user.getDefaultCompany().getCompanyCode() +"'
So try to add the same to the criteria
criteria.add(Restrictions.eq("companyCode",user.getDefaultCompany().getCompanyCode()));
Also it's not god to concate strings this way to get the query. SQL injection is possible. Use parameters instead.
Criteria and HQL is better than SQL in one case - you need DB independent logic to swap DB when necessary without rewriting code.
everyone. I'm new to Hibernate. And I'm making desktop application. I have 2 tables: Worker and Ceh (i.e. Department). Relation between them: many-to-one, i.e. 1 Ceh may contain many workers.
I run hql query with inner join to show info about all workers including name of the department and want to show the results in JTable.
The hql query:
private static String query_All_Workers="select W.fio, W.nomer, W.salary, C.name from Worker W Inner Join W.ceh C;
The method that runs query:
try {
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Query q = session.createQuery(hql);
List resultList = q.list();
displayResult(resultList);
session.getTransaction().commit();
} catch (HibernateException he) {
he.printStackTrace();
}
The method displayResult(List resultList):
Vector<String> tableHeaders = new Vector<>();
tableHeaders.add("FIO");
tableHeaders.add("Nomer");
tableHeaders.add("Salary");
tableHeaders.add("Ceh");
Vector tableData = new Vector();
for(Object o : resultList) {
Worker worker = (Worker)o;
Vector<Object> oneRow = new Vector<Object>();
oneRow.add(worker.getFio());
oneRow.add(worker.getNomer());
oneRow.add(worker.getSalary());
oneRow.add(worker.getCeh());
tableData.add(oneRow);
}
resultTable.setModel(new DefaultTableModel(tableData, tableHeaders));
And the exception occurs like this:
"java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to
workers.entity.Worker"
It happens because the list contains objects which are results of inner join query. So I don't know how I can correctly cast the object to Worker entity in order to use its getters.
You’re getting the “java.lang.ClassCastException” because you are trying to cast object of type java.lang.Object to custom class Worker:
Worker worker = (Worker)o;
There’s nothing wrong with what you’re trying to do just make sure that the result set returns actually Worker, which is not the case. In your example you are returning resultSet of Objects, because you’re writing regular JDBC select SQL statement.
In order to fix that you will need to checkout Hibernate’s Query Language (HQL) syntax and write HQL query instead of regular JDBC one.
Quick tutorial here http://www.tutorialspoint.com/hibernate/hibernate_query_language.htm
I will advise you do to so from now on, because you will gain the following benefits:
When you write select statements (or any other for that matter) with HQL you think and use Java objects, not DB tables (it helps a lot with table foreign key mappings);
HQL returns whole Java object back since Hibernate will do the necessary conversion for you.
In your case you just need to replace the query_All_Workers with this: “from Worker”. Yup, that’s it! Looks weird but as I said before, Hibernate is taking care of all conversions;
Once you’ve done that, and assuming that your Java class is properly mapped to Hibernate entity, resultSet will contain Workers this time, from which you can easily extract Ceh’s name by using Java getter method:
worker.getCeh.getName();
Also using HQL you will not need to make a second select to Ceh table, just to get the name, like you need to do right now.
Hope that helps.
I would like to get elements of a collection (Set<SheetConfig>) for a set of objects (WorkbookConfig) from Hibernate without getting the primary objects(WorkbookConfig).
The underlying tables look like this:
workbook_config -> workbook_config_sheet_join <- sheet_config
If I just run it in my SQL utility, a successful SQL statement looks like this:
SELECT DISTINCT sheet_config_id FROM sheet_config AS sc
LEFT JOIN workbook_config_sheet_join AS wcsj
ON sc.sheet_config_id = wcsj.sheet_config_id
LEFT JOIN workbook_config AS wc
ON wc.workbook_config_id = wcsj.workbook_config_id
WHERE wc.group_id ="1"
ORDER BY sheet_name;
I would like to do this properly without using HQL.
My UNSUCCESSFUL attempt has resulted in this:
#SuppressWarnings("unchecked")
public List<SheetConfig> findAllForUser() {
List<SheetConfig> sheetConfigs = null;
Session session = getSession();
Criteria crit = session.createCriteria(WorkbookConfig.class)
.add(Restrictions.in(GROUP, getGroupsForUser()))
.setFetchMode(SHEET_CONFIGS, FetchMode.JOIN);
sheetConfigs = (List<SheetConfig>) crit.list();
return sheetConfigs;
}
This is still giving me WorkbookConfigs, but what I would like to do in a single pass is get SheetConfigs. I have spent the day on the Internet trying to find a coherent explanation of the Hibernate API, and I haven't been able to find what I would think is a solution to a fairly common requirement. I can always back out and just do most of the work in Java, but it seems like I should be able to do this with the Hibernate API. I appreciate any help, and also, if you can recommend a reference that explains not simply querying collections, but returning them, I would be grateful.
Did you look into the setProjection method on Criteria?
Using the setProjection method lets you select properties or objects from the executed query.
Hibernate Criteria documentation
I have the following code in java.
List<UserHelper> users=List<UserHelper>)session.getNamedQuery("PkUser.loadHelperUsers").list();,
I think it does not matter what the "UserHelper" class is that's why I do not write it, not to overload my question. This is my namedQuery mentioned above.
#NamedQuery(name = "PkUser.loadHelperUsers", query = "SELECT new ge.tec.pto.ext.helpers.UserHelper(u) from PkUser u order by u.pkUserId desc"),
The problem is that the hql selects too many rows, I think the same number of rows that is in database in pk_user table.If anyone knows how to fix this please inform me. It will be very nice if the solution will not require to alter my "NamedQuery", It will be graet if I will have to change only my Query creation, But any solutions will be helpful, Thank you
Multiple selects when using Key word “`new`” in `hql`
There is no problem with your code and with NEW keyword .
Your query will return all the Rows in the UserHelper related Table
You should use a WHERE clause to get the required rows .
EX :
query = "SELECT new ge.tec.pto.ext.helpers.UserHelper(u) from PkUser u where username=:passedparamer order by u.pkUserId desc"