Our application is deployed on weblogic
we use Hibernate and spring
The session factory is created through a user defined class which creates SessionFactories by reading the hibernate.cfg.xml file
So these are the steps :
Our custom class is defined in spring application context and we inject the format of theCFG xml file in this class constructor :
<bean id="myCustomFactoryCreator"
class="com.xyz.CustomFactoryCreator"
singleton="true">
<constructor-arg>
<bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" >
<property name="staticField">
<value>com.xyz.MyConstants.HIBERNATE_CFG_XML</value>
</property>
</bean>
</constructor-arg>
</bean>
In MyConstants.java:
public static final String HIBERNATE_CFG_XML = ".hibernate.cfg.xml";
So this way in the constructor - the code will iterate over all such files ending with ".hibernate.cfg.xml"
I will have different files for different clients :
"Client1.hibernate.cfg.xml" and "Client2.hibernate.cfg.xml" and so on ......
The code will iterate over all such files and create SessionFactories and then embed them into Springs HibernateTemplate and then store them in a map against the client name as key value pair :
i.e. Client1 , HibernateTemplate1
Client2 , HibernateTemplate2 and so on
I hope you get the picture
This bean "myCustomFactoryCreator" is then injected into my Dao:
<bean id="myCustomDao"
class="com.xyz.MyCustomDao"
lazy-init="true">
<property name="criteriaConverter" ref="criteriaConverter" />
<property name="myFactory" ref="myCustomFactoryCreator" />
</bean>
An example of my Hibernate.cfg.xml is as : ( I have multiple such files where schema name changes for each client )
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">MYDS</property>
<property name="show_sql">true</property>
<property name="default_schema">CLIENT1SCHEMA</property>
</session-factory>
In my Dao - based on the client login - I get the appropriate HibernateTemplate and fire selects against the database
Here we are using "DetachedCriteria" - sample code as follows :
List<T> inObjList=HibernateTemplate.findByCriteria(DetachedCriteria, 0, 100);
So this is all fine and this works well
This was when we were using Hibernate prior to 4.x
Thanks for your patience till now - will now get to the problem
With Hibernate 4.x - I cannot any longer use Springs Hibernate Template
Even if there is a way to use it - for reasons beyond my control I will not be allowed to use it - so I must go the SessionFactory route
So following the same logic as above - I stored in a map clientName and SessionFactory as against storing HibernateTemplate
The difference was that now I could no longer use - HibernateTemplate.findByCriteria()
So what I did was got the SessionFactory from the map and then tried to get a session:
Session session=testSessionFactory.getCurrentSession();
This failed with the error at above line with the exception :
org.hibernate.HibernateException: No CurrentSessionContext configured!
So did a bit of googling and looking at solutions in stackoverflow - I added the following line in my CFG files - I am not 100% sure if it is correct but used it assuming that mine being a managed environment where I am using weblogic managed datasource it would be JTA:
<property name="hibernate.current_session_context_class">jta</property>
This got me by the first exception - but then I hit the second exception :
org.hibernate.HibernateException: createCriteria is not valid without active transaction
at the following line of code :
Criteria subSelectCriteria =session.createCriteria(getType());
I come from the humble jdbc world - so I thought no big deal - I will simply add some transaction ala jdbc in the code - so I added this :
Transaction tx = null;
session.beginTransaction();
Criteria subSelectCriteria =session.createCriteria(getType());
tx.commit();
It failed at the above commit with the error :
Caused by: org.hibernate.TransactionException: unable to commit against JDBC connection
at org.hibernate.engine.tx.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:116)
at org.hibernate.engine.tx.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:180)
Caused by: java.sql.SQLException: Cannot call Connection.commit in distributed transaction.
Transaction Manager will commit the resource manager when the distributed tx is committed.
at weblogic.jdbc.wrapper.JTSConnection.commit(JTSConnection.java:663)
So then in my Hibernate CFG file I added the following line and removed the transaction management in my Java code in my Dao :
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
This gave the error :
org.hibernate.HibernateException: No TransactionManagerLookup specified
So please advise what I should do - and thanks for bearing with me on a long post
NOTE - I did find a solution where I can define each SessionFactory as a bean in spring and inject each of these into a
org.springframework.orm.hibernate4.HibernateTransactionManager
However that would mean for each SessionFactory I would need to manually define a bean and inject the HibernateTransactinManager
Thank you !
See Question&Answers more detail:
os