MyEclipse Hibernate Spring tutorial – Managing Hibernate transaction in Spring

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.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="file:src/hibernate.cfg.xml">
</property>
</bean>
<bean id="userDAOTarget" class="com.myeclipse.hibernatespring.UserDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="userDAOService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="target"><ref local="persistenceLayer"/></property>
</bean>

<bean id="persistenceLayer"
class="com.myeclipse.hibernatespring.PersistenceLayer"
abstract="false" singleton="true" lazy-init="default"
autowire="default" dependency-check="default">
<property name="userDAO">
<ref bean="userDAOTarget" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
</beans>

10061 error while installing MySQL on Windows Vista

I really had a very tough time today while installing MySQL on vista. All the steps in the installation are simple and self-explanatory. I just want to mention two things from my experience

Before starting installation

1) If you want to install MySQL after uninstall, delete your current MySQL fully and properly. After uninstall you should manually delete the installation folder at c:Program FilesMySQL or at any location your MySQL is installed.

2) Turn off UAC(the nasty part of Windows Vista)

3) Turn off Windows Firewall.

4) Restart your PC.

5) Try now. This time the installation should be smooth and easy

org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing:

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.

 

ORA-01747: invalid user.table.column, table.column, or column specification

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.

org.hibernate.QueryParameterException: could not locate named parameter

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.

synchronization in DWR

      3 Comments on synchronization in DWR

AJAX(Asynchronous JavaScript + XML) got its name because of its ability to interact asynchronously. This makes Ajax famous for the Rich Internet Applications aka RIAs.

But sometimes you purposefully need synchronization in your code. I needed it once. I was calling the same business method consecutively from my ajax code for two different fields. Even after synchronizing the business method and making it thread safe,I was not able to guarantee that the first method was fully finished before the second starts. Sometimes the first DWR call was processing the returned values and in the meantime second DWR call will return and mess with the original returned values. I had to synchronize the calls to make sure that both the calls get fired and completed in a proper order.

Starting from DWR1.1 you can synchronize your method calls at various levels.

I synchronized at the method level. My normal ajax code looked like myBusinessManagerImpl.getValues(‘param1’, setValuesInDWR);

Where

myBusinessManagerImpl – business layer class

getValues – the method called by Ajax

param1 – the parameter passed to the business method

setValuesInDWR – the function variable, which was defined somewhere in the code like

var setValuesInDWR = function(data){
//….DWR Code…..
};

To make the method calls synchronized I modified the method call like this

myBusinessManagerImpl.getValues(‘param1’, {callback:setValuesInDWR, async:false});

This way I was able to make two consecutive calls to the same method synchronously.

addOptions problem in DWR

      6 Comments on addOptions problem in DWR

Have you ever wondered why the addOptions is not working in DWR even after reading the specs carefully. It happened to me recently. First, of all, the API or specs or documentation for DWR(addOptions Documentation) are not detailed and sufficient. Especially, for the new and impatient learners like me, who don’t want to go through each and every page of the spec before using the technology. Second, if you are impatient and new learner then probably you might have missed some of the part. Problem: I was trying to populate the Select box from a list of Objects using the addOptions method of DWR. I have followed the documentation fully but my drop down was not being populated. (It was my second day with DWR so I didn’t know some of the complexities which ultimately solved the problem)

Solution:- I will take one example to explain this Let your select field something like this



<select id="statesList" />

And the class whose list of Objects you are trying to add is something like this



package testPackage.dwr;
public class State{
private String stateId;
private String stateName;
............
//getter and setter methods
............
}

and you want to populate this using DWR after some user action. Make sure that your callback function looks like this



var setValuesInDWR = function(data){
var fieldId = 'statesList';
var valueText = 'stateId';
var nameText = 'stateName';
dwr.util.removeAllOptions(fieldId);// step 1
dwr.util.addOptions(fieldId, data, valueText, nameText);//step 2
};


All the above steps are important

Step 1 – Actually removes the already existing values from your select list. If you don’t do this. the addOptions method will simply append the list.

Step 2 – This will actually add the values to the drop-down list.

I forgot/missed/didn’t know that you have to add the following line in dwr.xml

<convert converter=”bean” match=”testPackage.dwr.State”/>

Reason is, unless you don’t explicitly specify in your dwr.xml the user defined beans will not be converted in DWR. If your bean consists of supported datatypes which DWR can automatically convert then you can just add this declaration. After following all these steps carefully the problem of Dropdown not getting populated in DWR should be solved.

JRun Error – Exception parsing the TLD null : The tag function on line 14 is not a valid TLD element

Problem – Last week we had hard time with this problem. Our Web App was running all fine on Tomcat 5. But when we deployed our application on JRun we got

Exception parsing the TLD null : The tag function on line 14 is not a valid TLD element

Solution: – Carefully look into the Jars you are using in the classpath. In the most probability some of the Jars have some tlds which are incompatible with the JRun expects. Try removing all the Jars and carefully add only the required Jars checking the compatibility of the Jars one by one. See the explanation section below for the more details.

Explanation:- The error itself says that there is some TLD parsing error. The tag which JRun is trying to parse is having a different TLD than Jrun expects. If you look into Jrun.jar you will find a file called JSP.tld. It says tld version as 1.2. In our case we were having standard-1.1.2.jar in our classpath. That was the root cause of the problem. In fact this jar was not required at all. It was just sitting there in one of the common Jar repository. This solved our problem. You can think of looking into the struts.jar, servelet-api jars and Spring jars to check the compatibility with your JRun jars

Hibernate Error – Identifier of an instance altered from 1 to 1

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>

/hibernate.cfg.xml not found

      14 Comments on /hibernate.cfg.xml not found

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 under src folder.