Posts filed under 'Hibernate'
I got this error today.
Caused by: org.hibernate.hql.ast.QuerySyntaxException: unexpected end of subtree [select count(*) from com.test.Fruits as fruit where fruit.fruitId in () order by fruit.fruitName desc ]
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:31)
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:24)
at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:59)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:235)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:160)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1113)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at com.test.FruitDAOServiceImpl.fruitCount(FruitDAOServiceImpl.java:682)
at jrockit.reflect.VirtualNativeMethodInvoker.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;(Unknown Source)
at java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;I)Ljava.lang.Object;(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:139)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
While there could be many reasons because of which this error comes. For me, the problem was that the parameter list I was passing was empty.
I was getting all the fruits for which fruit id is in the fruitIdList I was passing as the query parameter. If the fruitIdList is emply list then this problem comes. I solved it by conditionally framing query based on the list. That is instead of
public Long fruitCount(List fruitIdList){
........
Query fruitQuery = getSession().createQuery("select count(*) from com.test.Fruits as fruit where fruit.fruitId in (:fruitIdList) order by fruit.fruitName desc ");
fruitQuery.setParameterList("fruitIdList", fruitIdList);
List fruitCountList = fruitQuery.list();
..........
}
I did this
public Long fruitCount(List fruitIdList){
........
StringBuffer queryString = new StringBuffer("select count(*) from com.test.Fruits as fruit ");
if(fruitIdList !=null && !fruitIdList.isEmpty()){
queryString.append(" where fruit.fruitId in (:fruitIdList) ");
}
queryString.append(" order by fruit.fruitName desc ");
Query fruitQuery = getSession().createQuery(queryString.toString());
if(fruitIdList !=null && !fruitIdList.isEmpty()){
fruitQuery.setParameterList("fruitIdList", fruitIdList);
}
List fruitCountList = fruitQuery.list();
..........
}
In short, append the collection parameter in the query and the query parameter only if the collection is non-empty.
December 9th, 2008
Collection mappings in Hibernate can be configured to sort using a specific comparator.
Consider the following mapping
......
......
In the example above Hibernate will order the bankAccounts set according to their natural order. If the BankAccout class implements Comparable interface, compareTo method will be used to sort the Set.
What if you want to sort the set differently? What if you want to use a comparator to sort the set.
The sort attribute can have three possible values
The first option is
which sorts by natural order
the second option is
which tells Hibernate that the Set needs not to be sorted
and the third option is
where you specify what comparator should be used to sort the Set.
Let’s see it through code example. For example suppose class BankAccount is defined as below
package com.example;
//import statements
public class BankAccount implements Comparable, Serializable{
private String accountName;
private String accountShortName;
//getter and setter methods
public int compareTo(BankAccount that) {
final int BEFORE = -1;
final int AFTER = 1;
if (that == null) {
return BEFORE;
}
Comparable thisAccountName = this.getAccountName();
Comparable thatAccountName = that.getAccountName();
if(thisAccountName == null) {
return AFTER;
} else if(thatAccountName == null) {
return BEFORE;
} else {
return thisAccountName.compareTo(thatAccountName);
}
}
}
In this case sort=”natural” will sort using the above compareTo method which compares the accountName to sort.
Now suppose you want that for this specific mapping you want the collection to be sorted by, say, accountShortName. You will define a Comparator like this
package com.example;
//import statements
public class BankAccountShortNameComparator implements Comparator{
public int compare(BankAccount o1, BankAccount o2) {
if(o1!=null && o2!=null && o1.getAccountShortName()!=null && o2.getAccountShortName()!=null) {
return o1.getAccountShortName().compareTo(o2.getAccountShortName());
}
if(o1!=null && o2!=null) {
return o1.compareTo(o2);
}
return 0;
}
}
Then your mapping will say something like this
In this way Hibernate will use your custom Comparator to sort the set
November 10th, 2008
This is continuation of my earlier post on org.hibernate.TransientObjectException. Let me write the scenario again
<class name=”com.xxx.A” table=”A” schema=”TESTSCHEMA”>
<id name=”aId” type=”java.lang.Long”>
<column name=”A_ID” precision=”29″ scale=”0″ />
</id>
…………………..
some more mapping elements
…………………..
…………………..
<many-to-one name=”bId” class=”com.xxx.B” fetch=”select”>
<column name=”B_ID” precision=”29″ scale=”0″ />
</many-to-one>
…………………..
A is referring to B using a primary key column of bId of B.
In that post I have mentioned that if B is a transient object and you don’t want to persist the value of B to A then just tell the hibernate to ignore that value by saying
update=”false” insert=”false” in the many to one mapping.
But what if you want to persist the value of foreign key in A.
Then the approach is different. You have to make sure that instance B is persistent not transient.
That is if your code says something like
A a = new A();
B b = new B();
a.setB(b);
…..
…..
session.save(a);
you are in trouble. Because B is in transient state. You have to attach b to the session.
There may be other ways of attaching this transient object to session. The approach I am following is simple. I am reading the value of B from the database using Hibernate. That way, hibernate attaches B to session and it is then a persistent object.
That is I do something like
A a = new A();
B b = session.get(B.class, new Long(1));
a.setB(b);
…..
…..
session.save(a);
I won’t get any exception because this time there is no transient object to save. All the objects are persistent.
Powered by ScribeFire.
January 28th, 2008
Spring transaction management, Hibernate transaction management in Spring
There was a problem/defect in the MyEclipse tutorial on Hibernate Spring. It was not a major problem. The tutorial demonstrates the Spring and Hibernate functionality pretty well. The only problem was that the code does seems to work properly. Because of absence of proper transaction management in code the data was not getting persisted in the database. Because of the caching in Hibernate it seems to the user that the data is being written to the database and then read back.
There are two solutions to the problem. One is to write the transaction management code in the java class itself. Another is to manage transaction via Spring’s transaction management. The second solution makes more sense because it shows of the Spring’s capability of managing transaction in Hibernate. You can see both the solutions here.
I am writing the Spring’s configuration for Hibernate transaction management again.
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
January 20th, 2008
I was getting this error today.
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:This is the problemTable A was referring to the talbe B using a foreign key
hbm.xml for A looked like this
<class name=”com.xxx.A” table=”A” schema=”TESTSCHEMA”>
<id name=”aId” type=”java.lang.Long”>
<column name=”A_ID” precision=”29″ scale=”0″ />
</id>…………………..
some more mapping elements
…………………..
…………………..
<many-to-one name=”bId” class=”com.xxx.B” fetch=”select”>
<column name=”B_ID” precision=”29″ scale=”0″ />
</many-to-one>
…………………..
I just want to save A with some new value and A will refer to B using some foreign key. But in my transaction I am not going to change B and save the changes. Therefore the many-to-one mapping above is wrong. It does not tell hibernate that class b is immutant. That is it is not going to change. Hibernate thinks that the referred table is not saved therefore it complains and says
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:
Please note that in this case B is transient object. If you don’t really want to save the value of B(transient object) in A , then to get rid of this problem change the many-to-one mapping as
update=”false” insert=”false” fetch=”select”>
But if you want to save the value of B then see my other post
That is, tell hibernate that you are not going to change the values of B, you are just fetching it.
January 14th, 2008
Today I got this error.
ORA-01747: invalid user.table.column, table.column, or column specification.
There could be many reasons why you can get this error. But the basic reason is the query which is finally getting executed to your database is wrong in some way. In my case, I had a column with column name as DESC. I got rid of this problem by simply dropping the table and creating a new one with column name DESCRIPTION instead of DESC. You may not be able to do that if the table is already existing with many records in it. 
Other reason could be that, if you are using named query your named query is not syntactically right.
No matter how the you get this error or for that matter any DB error in Hibernate, the best approach is to enable the show_sql variable in hibernate configuration and get the final query which hibernate is firing against the database.
Get this query and try running it directly in your database client. You can easily find out the culprit part of the query from there. Once you find out root cause of the problem you can think of workarounds or solution for this problem.
And yes, don’t forget to turn off the show_sql parameter after you are done with it. It will unnecessarily clutter your logs.
January 9th, 2008
When you query the database in Hibernate using NamedQuery you may run into this error
org.hibernate.QueryParameterException: could not locate named parameter [parm1]
Chances are that you are either trying to set a parmeter to the query which infact doesn’t exist in your query. For example
you are trying to do
query.setParameter(”parm1″, new Long(parm1Value));
whereas, in query there is no parameter like parm1
i.e. query might be just “from Item item”
Or you might be committing some spelling mistake in your code
Eg. query.setParameter(”pram1″, new Long(parm1Value));
and query is “from Item item item.desc like :parm1″
Do note that your parameter name in Java Class is misspelt as pram1 instead of parm1.
January 8th, 2008
Problem:-Getting the error ” identifier of an instance of com.sample.db.Sample altered from 1 to 1″
Solution:- Check whether the java type of the identifier field in the Data Object, the type of the field in the hibernate xml file and the type of the column in the database are compatible types or not.
Explanation:- I had faced this strange problem today. I am using struts, hibernate and spring.
I found out that the problem roots from
public void
checkId(Object object, EntityPersister persister, Serializable id, EntityMode entityMode) method of DefaultFlushEntityEventListener class.
I solved this problem by changing the type of the id field in the class and the hbm.xml file.
We made some mistakes in declaring getter and setter methods and id field for this object. (therefore it is advisable to use Hibernate tools or other reverse engineer tools to generate your data object and hbm files)
The sample class was as follows
class Sample{
integer sampleId;
String sampleName;
public int getSampleId(){
….
}
public void setSampleId(int i){
…..
}
}
And this was the hbm file declaration
<id
name=”sampleId”
type=”integer”
column=”sample_id”
unsaved-value=”0″>
<generator class=”identity” />
</id>
<property
name=”sampleName”
type=”string”
column=”sample_name”
length=”50″
not-null=”true”
unique=”true”
/>
The problem was that in the database the type of the field was smallint which corresponds to the short data type in Java. Therefore somewhere in the org.hibernate.type.Type class hierarchy the
public boolean isEqual(Object x, Object y, EntityMode entityMode) method was failing.
What I did is I modified the Data Object and the hbm file like this
class Sample{
integer sampleId;
String sampleName;
public int getSampleId(){
public short getSampleId(){
….
}
public void setSampleId(int i){
public void setSampleId(short s){
…..
}
}
<id
name=”sampleId”
type=”integer”
type=”short”
column=”sample_id”
unsaved-value=”0″>
<generator class=”identity” />
</id>
May 16th, 2007
Problem: Many a times we get a problem in hibernate saying /hibernate.cfg.xml not found
Solution: As per Java Persistence with Hibernate book, you should keep the hibernate configuration file directly in the source directory of your project outside any package. In Rational Application Developer, I have solved this problem by placing it directly src folder.
March 18th, 2007