我的配置 spring sessionFactory 配置有什么问题?
What's wrong in my confguration spring sessionFactory configuration?
首先,我不能使用Spring的@Transactional
注解。我必须完全使用 EJB 容器中的 JTA。目前我正在使用 JBoss AS 7.0 Web-Profile
。所以我需要做的是配置 Hibernate 的会话工厂以正确地使用 Spring
环境中的 JTA
-transaction。我当前的配置:
部分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)
如何正确配置?
首先删除 JtaTransactionManager
的声明,因为 <tx:jta-transaction-manager />
已经提供了该声明。
接下来,您没有理由不能在 JTA 环境中使用 @Transactional
,这是声明式 tx 管理的全部要点。
您应该将配置的 jta transactionmanager 连接到 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
是在 JNDI 中以名称 java:jboss/TransactionManager
而不是其中之一注册的well-known names。您将需要自己声明 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
中注入它,因为它会自行查找。
首先,我不能使用Spring的@Transactional
注解。我必须完全使用 EJB 容器中的 JTA。目前我正在使用 JBoss AS 7.0 Web-Profile
。所以我需要做的是配置 Hibernate 的会话工厂以正确地使用 Spring
环境中的 JTA
-transaction。我当前的配置:
部分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)
如何正确配置?
首先删除 JtaTransactionManager
的声明,因为 <tx:jta-transaction-manager />
已经提供了该声明。
接下来,您没有理由不能在 JTA 环境中使用 @Transactional
,这是声明式 tx 管理的全部要点。
您应该将配置的 jta transactionmanager 连接到 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
是在 JNDI 中以名称 java:jboss/TransactionManager
而不是其中之一注册的well-known names。您将需要自己声明 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
中注入它,因为它会自行查找。