Spring,No Hibernate Session绑定到线程

时间:2013-12-04 08:02:16

标签: multithreading spring hibernate

我收到了这个错误,我不明白为什么会这样。

我已经定义了我的transactionManager:

<bean id="transactionManager"
    class="com.transaction.data.HibernateTransactionManager"> --> my own class
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="txTemplate" abstract="true"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager" />
    <property name="transactionAttributes">
        <props>
            <prop key="get*">
                PROPAGATION_SUPPORTS,ISOLATION_READ_UNCOMMITTED,readOnly
            </prop>
            <prop key="list*">
                PROPAGATION_SUPPORTS,ISOLATION_READ_UNCOMMITTED,readOnly
            </prop>             
            <prop key="*">
                PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE
            </prop>
        </props>
    </property>
</bean>

我已经定义了这样的bean:

<bean id="managerImpl" parent="txTemplate"  scope="singleton"> --> I undersstand that it's inside a transaction and it should be work only with this.
    <property name="target">
        <bean class="com.myapp.manager.ManagerImpl">
            <property name=".." --> many DAO's      
        </bean>
    </property>
</bean> 

<bean id="engine" class="com.engine.EngineImpl" scope="prototype">
    <property name="manager" ref="manager"/>
</bean> 

我的MVC控制器

<bean name="/user/main.htm"
    class="com.pragsis.bidoop.aw.ctrl.user.MainController">
    <property name="engine" ref="engine" />
    <property name="formView" value="public.init"/>     
    <property name="successView" value="public.init" />
</bean>

在我的代码中,我在我的控制器内部创建了一个Thread。这个线程有一个Engine bean,我用来自我的DAO的getCurrentSession从Hiberante获得一个Session。当我这样做时,我得到了例外。我做过的一件事,就是改变我的“引擎”的声明并将其作为“txTemplate”的父级并且它有效,但是,我不明白为什么它不起作用如果它只是我的经理“txManager”的孩子。 我知道Hiberante中的Session不是线程安全的,它们是在事务中创建的,但我知道我的“经理”在一个事务中。

更新: 我的控制器的代码是:

@Override
protected ModelAndView onSubmit(final HttpServletRequest request,
        final HttpServletResponse response, final Object command,
        final BindException errors) throws Exception {
   ...
        ExecuteEEThread execute =
                new ExecuteEEThread(engine, HDFSfileSystem);
        execute.start();

        HttpSession sesion = request.getSession();
        sesion.setAttribute("status", execute.getStates());
    }



return mav;
    }

我的主题是:

public final class ExecuteEEThread extends Thread {    
    @Override
    public void run() {
        boolean executing = true;
       ....
        try {
            if (executing) {
                states.put("EE", EXECUTING);                    
                engine.process();
                states.put("EE", END);

                if (log.isDebugEnabled()) {
                    log.debug("Engine ended.");
                }
            }
        } catch (Exception ex) {
            ....
        }
....
    }    

最后,我在我的经理中执行的代码类型以及我获得异常的地方是一个像这样的简单DAO。

 private void configurationSet() {
        List<TableUser> rtList =
                manager.getTableUserDAO().list(0, Integer.MAX_VALUE); --> excepcion

       ......
    }
@Override
    @PostFilter("filterObject.owner==null or hasRole(filterObject.owner)")
    public List<TableUser> list(final int init, final int maxValue) {
        final Session session = sessionFactory.getCurrentSession(); --> exception
        return crit.list();
    }

我对我正在使用的HibernateTransactionManager错了。我使用过这个。

 * @author Juergen Hoeller
 * @since 3.1
 * @see #setSessionFactory
 * @see #setDataSource
 * @see org.hibernate.SessionFactory#getCurrentSession()
 * @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection
 * @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
 * @see org.springframework.jdbc.core.JdbcTemplate
 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
 * @see org.springframework.transaction.jta.JtaTransactionManager
 */
@SuppressWarnings("serial")
public class HibernateTransactionManager 

1 个答案:

答案 0 :(得分:0)

从删除TransactionProxyFactoryBean开始,因为它使用起来很麻烦,并且会导致一点上的错误(注入错误的依赖性非代理实例等)。您正在使用Spring 3.1(或hihger)与Hibernate 4。

我建议您在@Transactional课程中使用com.myapp.manager.ManagerImpl

@Transactional
public class ManagerImpl extends Manager {}

然后在您的配置中添加<tx:annotation-driven />而不是TransactionProxyFactoryBean(如果您有更多,则可以删除所有这些内容)。我将从类级别的@Transactional开始,看看是否可以使它工作,如果它可以根据您当前的配置修改不同的方法。

你的经理是交易性的,但你要做的第一件事就是通过直接调用dao来绕过所有交易(你甚至可以在经理上使用丑陋的getter)。

manager.getTableUserDAO().list(0, Integer.MAX_VALUE);

上面的代码绕过了所有事务配置。你的经理应该有一个列出用户的方法(或者使TableUserDao也是事务性的(现在应该只是添加@Transactional)。

您正在JEE容器中启动线程,这基本上是您不应该做的事情。我强烈建议使用spring TaskExecutor抽象。您可以创建一个prototype范围的bean来表示您要执行的任务,并将其简单地传递给执行程序。这为您提供了一个可重用的ThreadPool和与容器线程管理的良好集成,旁边它还允许spring将依赖项注入您的任务(而不是自己这样做)。并让您免于与Thread自己合作。