Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

spring - Transaction Management using Hibernate with weblogic

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.5k users

...