我的配置spring sessionFactory配置有什么问题?

时间:2015-01-08 08:15:33

标签: java spring hibernate

首先,我无法使用Spring的@Transactional注释。我必须使用完全在EJB容器中的JTA。我很快就使用了JBoss AS 7.0 Web-Profile。所以我需要做的是配置Hibernate的会话工厂以正确使用JTA - Spring环境中的事务。我目前的配置:

context.xml配置的一部分:

<tx:annotation-driven/>
<tx:jta-transaction-manager  />

<!-- Some other beans -->

<bean id="userTransaction" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/UserTransaction"></property>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="annotatedClasses">
        <list>
            <value>com.badmitrii.db.entity.Employee</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
        </props>            
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="userTransaction" ref="userTransaction"></property>
</bean>

DAO-方法:

public Player getPlayerById(Integer id){
    try {
        userTransaction.begin();
    } catch (Exception e) { }

    //Here is obtaining a Criteria object and setting Restrictions

    try {
        userTransaction.commit();
    } catch (Exception e) { }
    return (Player) criteria.uniqueResult();
}

但是,当我尝试在DAO方法中获取Session时,我得到了以下的解释:

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
    org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1024)
    com.badmitrii.db.dao.EmployeeDAOImpl.getEmployeeById(EmployeeDAOImpl.java:34)
    com.badmitrii.EmployeeListController.getEmployeeById(EmployeeListController.java:42)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:483)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

如何正确配置?

1 个答案:

答案 0 :(得分:1)

首先删除JtaTransactionManager的声明,因为<tx:jta-transaction-manager />已经提供了声明。

接下来没有理由不能在JTA环境中使用@Transactional,这是声明性tx管理的全部要点。

您应该将已配置的jta事务管理器连接到LocalSessionFactoryBean以切换使用过的CurrentSessionContext

<tx:annotation-driven/>
<tx:jta-transaction-manager  />

<!-- Some other beans -->

<bean id="userTransaction" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/UserTransaction"></property>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jtaTransactionManager" ref="transactionManager" />
    <property name="annotatedClasses">
        <list>
            <value>com.badmitrii.db.entity.Employee</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
        </props>            
    </property>
</bean>

然后在你的鳕鱼中,你可以简单地做这样的事情

@Transactional
public Player getPlayerById(Integer id){
    //Here is obtaining a Criteria object and setting Restrictions
    return (Player) criteria.uniqueResult();
}

<强>更新

对于JBoss,<tx:jta-transaction-manager />不起作用,因为JTA的TransactionManager在名称为java:jboss/TransactionManager而不是well-known names之一的JNDI中注册。您需要自己声明JtaTransactionManager bean并删除<tx:jta-transaction-manager />元素。对于查找,您需要指定transactionManagerName或自己进行JNDI查找。

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManagerName" value="java:jboss/TransactionManager" />
</bean>

UserTransaction是在默认名称下注册的,因此您可以在JtaTransactionManager中省略它的注入,因为它会进行查找。