Hibernate:事务未成功启动(线程webapp)问题!

时间:2010-02-25 10:51:05

标签: hibernate transactions multithreading

我在一个使用线程监听端口上的数据包并处理这些数据包的网络应用程序中遇到了这个严重的问题。

数据包的处理涉及数据库事务,所以基本上就像是:


Thread:
run () {
  try {
    ...
    fireMessageEvent(data);
    ...
  } catch (Exception e) {
  }
}

fireMessageEvent(data) {
  someclass.messageArrived(data);
}

SomeClass:
messageArrived(Data data) {
  try {
    someOtherClass.setData(data);
  } catch (Exception e) {
  }
}

SomeOtherClass:
setData (Data data)
{
  try {
   ..
   processDataPart1(data);
   processDataPart2(data);
   ..
  } catch (Exception e) {
  }
}

processDataPart1(data)
{
    daolayer.getSomeObjectFromDatabase(x);
    ..
    daolayer.save(y);
    ..
    someotherDaolayer.update(a);
    ..
}

processDataPart2(data)
{
    daolayer.getSomeObjectFromDatabase(x);
    ..
    daolayer.save(y);
    ..
    someotherDaolayer.update(a);
    ..
    daolayer.save(b);
    ..
}


问题是我得到一个例外'交易没有成功启动'。同样有趣的是,异常被线程中的catch捕获,因此不会保存数据(可能是由于回滚。?。)。 目前,我创建了另一个虚拟对象以保存在数据库中然后将其删除,这样当异常发生时,它的虚拟对象不会被保存,之前的对象会被保存。

有人可以帮忙吗?有人遇到过同样的问题吗?

以下是例外情况:

2010-02-25 10:30:33,759 INFO [packetInfo log] - Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started
2010-02-25 10:30:33,759 INFO [packetInfo log] - org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:659)
2010-02-25 10:30:33,759 INFO [packetInfo log] - org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
2010-02-25 10:30:33,759 INFO [packetInfo log] - org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
2010-02-25 10:30:33,759 INFO [packetInfo log] - org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
2010-02-25 10:30:33,759 INFO [packetInfo log] - org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
2010-02-25 10:30:33,774 INFO [packetInfo log] - org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
2010-02-25 10:30:33,774 INFO [packetInfo log] - org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
2010-02-25 10:30:33,774 INFO [packetInfo log] - com.comp.projectx.service.lear.communicator.AriadneListenerServiceImplementation$$EnhancerByCGLIB$$e5054dfb.setData()
2010-02-25 10:30:33,774 INFO [packetInfo log] - com.comp.projectx.service.lear.communicator.PLCListenerServiceImplementation.messageArrived(PLCListenerServiceImplementation.java:153)
2010-02-25 10:30:33,774 INFO [packetInfo log] - com.comp.projectx.service.lear.communicator.Listener.fireMessageEvent(Listener.java:229)
2010-02-25 10:30:33,774 INFO [packetInfo log] - com.comp.projectx.service.lear.communicator.Listener.run(Listener.java:94)

web.xml中的配置:

    hibernateFilter : org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    hibernateFilter url-pattern: *.95
    hibernateFilter url-pattern: /dwr/*
    lazyLoadingFilter: org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    lazyLoadingFilter url-pattern: /*

休眠配置:


    jee:jndi-lookup id="dataSource" jndi-name="/jdbc/kernstreamDS" resource-ref="true" expected-type="javax.sql.DataSource" 

    bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
        property name="dataSource" ref="dataSource" 
    bean

    bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"

在Dao图层中保存对象:


    getSession().saveOrUpdate(resultObj);

要检索:


    List resultObj = getSession().createCriteria(Lot.class)
            .add(Restrictions.eq("publicId", publicId)).list();

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

我解决了这个问题。如果其他人有同样的问题,我就是这样做的。

基本上,在dao层中,它使用的是Spring事务管理,而在其他位置则使用了hibernate事务管理。混合两者并不是一个好主意。 所以通过使用

更改dao层

的getSession()saveOrUpdate(...);

getHibernateTemplate()saveOrUpdate(...);

解决了这个问题。

谢谢大家的评论。

答案 1 :(得分:0)

我有类似的问题,在我的情况下连接有问题,显然如果没有连接则没有会话,如果没有会话没有事务。

    try {
            session = HibernateSessionFactory.getSessionFactory()
                    .openSession();
            session.beginTransaction();
            StringBuffer qry = new StringBuffer();
            qry.append(" select a.customer_key from customer as a where a.name= '"+siteName+"' ");
            query = session.createSQLQuery(qry.toString());
            customerList = (ArrayList) query.list();                
            session.getTransaction().commit();
        } catch (HibernateException hex) {
            session.getTransaction().rollback();                
            String msg = "Error occured in getCustomerId Cause: " + hex;
            logger.error(msg);
            throw new DAOException(msg);
        }finally{
            if(session != null){
                session.close();
            }
        }

在上面的代码段中,对甚至不存在的会话进行回滚。 这导致交易未成功启动。 所以我添加了一个嵌套的try catch块来避免这个错误。

所以我的修改后的代码看起来像这样。

try {
            session = HibernateSessionFactory.getSessionFactory()
                    .openSession();
            session.beginTransaction();
            StringBuffer qry = new StringBuffer();
            qry.append(" select a.customer_key from customer as a where a.name= '"+siteName+"' ");
            query = session.createSQLQuery(qry.toString());
            customerList = (ArrayList) query.list();                
            session.getTransaction().commit();
        } catch (HibernateException hex) {
        try{
            session.getTransaction().rollback();                
        }catch(Exception e){
        //just log warn
        }
            String msg = "Error occured in getCustomerId Cause: " + hex;
            logger.error(msg);
            throw new DAOException(msg);
        }finally{
            if(session != null){
                session.close();
            }
        }