【问题标题】:Hibernate: Transaction not successfully started (Threaded webapp) Problem!Hibernate:事务未成功启动(线程 webapp)问题!
【发布时间】:2011-01-20 23:03:25
【问题描述】:

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

一个数据包的处理涉及到数据库事务,所以基本上是这样的:

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] - 无法提交 Hibernate 事务;嵌套异常是 org.hibernate.TransactionException:事务未成功启动 2010-02-25 10:30:33,759 信息 [packetInfo 日志] - org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:659) 2010-02-25 10:30:33,759 信息 [packetInfo 日志] - org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732) 2010-02-25 10:30:33,759 信息 [packetInfo 日志] - org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701) 2010-02-25 10:30:33,759 信息 [packetInfo 日志] - org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321) 2010-02-25 10:30:33,759 信息 [packetInfo 日志] - org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116) 2010-02-25 10:30:33,774 信息 [packetInfo 日志] - org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 2010-02-25 10:30:33,774 信息 [packetInfo 日志] - org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635) 2010-02-25 10:30:33,774 信息 [packetInfo 日志] - com.comp.projectx.service.lear.communicator.AriadneListenerServiceImplementation$$EnhancerByCGLIB$$e5054dfb.setData() 2010-02-25 10:30:33,774 信息 [packetInfo 日志] - com.comp.projectx.service.lear.communicator.PLCListenerServiceImplementation.messageArrived(PLCListenerServiceImplementation.java:153) 2010-02-25 10:30:33,774 信息 [packetInfo 日志] - com.comp.projectx.service.lear.communicator.Listener.fireMessageEvent(Listener.java:229) 2010-02-25 10:30:33,774 信息 [packetInfo 日志] - com.comp.projectx.service.lear.communicator.Listener.run(Listener.java:94)

web.xml 中的配置:

hibernateFilter : org.springframework.orm.hibernate3.support.OpenSessionInViewFilter hibernateFilter url 模式:* .95 hibernateFilter url-模式:/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();

任何帮助将不胜感激。

【问题讨论】:

  • 您提供的代码似乎与问题无关。提供管理事务的代码/配置。
  • 我已经添加了配置/代码,希望有用。
  • 不知道线程中运行的代码是如何获取Session并处理事务的。
  • 基本上sessionFactory被注入到daoLayer中。并且将 DaoLayer 注入到处理数据的类中。

标签: hibernate transactions multithreading


【解决方案1】:

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

    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();
            }
        }

在上面的 sn-p 中,一个甚至不存在的会话发生回滚。 这导致事务未成功启动。 所以我添加了一个嵌套的 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();
            }
        }

【讨论】:

    【解决方案2】:

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

    基本上,在 dao 层,它使用 Spring 事务管理,而在其他位置,它使用 Hibernate 事务管理。将两者混合不是一个好主意。 因此,通过使用

    在 dao 层中进行更改

    getSession().saveOrUpdate(...);

    getHibernateTemplate().saveOrUpdate(...);

    解决了这个问题。

    谢谢大家的cmets。

    【讨论】:

    • HibernateDaoSupport 及其附带的 getHibernateTemplate() 方法正在逐步淘汰用于 hibernate4。建议完全切换到 getSession()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 2016-07-08
    • 1970-01-01
    相关资源
    最近更新 更多