【发布时间】:2014-08-13 22:38:38
【问题描述】:
所以我彻底经历了 Get is not valid without active transaction 并且知道我没有不自动装配 SessionFactory 的问题,并且遵循了最佳实践,但仍然遇到此异常:
org.hibernate.HibernateException: save is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
at com.sun.proxy.$Proxy31.save(Unknown Source)
at com.bms.dao.DemandManageDAOImpl.save(DemandManageDAOImpl.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy29.save(Unknown Source)
at com.bms.service.DemandServiceImpl.createDemand(DemandServiceImpl.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy30.createDemand(Unknown Source)
at com.bms.dao.DemandManageDAO_UT.testCreateDemand(DemandManageDAO_UT.java:69)
我将尝试包含分布在多个文件中的所有必要配置和代码。抱歉所有文件,并提前感谢您。 这是 Java 1.7、Spring 4.0.2.RELEASE、Hibernate 4.3.5.Final
这似乎是以前版本的例行公事。我可以通过获取会话并开始交易来解决这个问题,但我不想这样做。
上下文: 应用上下文.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- Database Configuration -->
<import resource="classpath:database/hibernate.xml"/>
<!-- Auto scan the components -->
<context:component-scan base-package="com.bms" />
<tx:annotation-driven/>
<bean id="demandManageDao" class="com.bms.dao.DemandManageDAOImpl"></bean>
<bean id="demandService" class="com.bms.service.DemandServiceImpl"> </bean>
</beans>
hibernate.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="classpath:database/dataSource.xml" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database/database.${demandEnv}.properties</value>
</property>
</bean>
<!-- Hibernate Session Factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.bms.demand.domain.data</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
数据源.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database/database.${demandEnv}.properties</value>
</property>
</bean>
<!-- HSQLDB Data Source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
</beans>
测试文件:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@TransactionConfiguration(transactionManager = "transactionManager",defaultRollback=true)
@Transactional
public class DemandManageDAO_UT {
private static ApplicationContext context;
private SessionFactory sessionFactory;
private DemandManageDAO demandManageDAO;
private DemandService demandService;
@BeforeClass
public static void setUpClass(){
context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
}
@Before
public void setUp() throws Exception {
demandManageDAO = (DemandManageDAO)context.getBean("demandManageDao");
demandService = (DemandService)context.getBean("demandService");
sessionFactory = (SessionFactory)context.getBean("sessionFactory");
}
@After
public void tearDown() throws Exception {
}
@Test
public void testCreateDemand() throws Exception {
Demand myDemand2 = new Demand();
myDemand2.setId(10L);
myDemand2.setDescription("text");
myDemand2.setMonths(1);
Calendar calendar = Calendar.getInstance();
calendar.set(2000, 7, 4);
myDemand2.setStartDate(calendar.getTime());
Availibility availibility = new Availibility();
availibility.setId(2L);
availibility.setMonth(calendar.getTime());
availibility.setPercentage(new Integer(50));
availibility.setResourceName("text");
myDemand2.addAvailibility(availibility);
Long perId = demandService.createDemand(myDemand2);
assertThat(perId,is(myDemand2.getId()));
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Availibility sessionObject = (Availibility) session.get(Availibility.class, 2L);
assertThat(sessionObject.getResourceName(),is("text"));
}
}
服务实现
@Component
public class DemandServiceImpl implements DemandService {
@Autowired
DemandManageDAO demandManageDao;
public void setDemandManageDao(DemandManageDAO demandManageDAO) {
this.demandManageDao = demandManageDAO;
}
@Override
@Transactional
public Long createDemand(Demand myDemand2) throws Exception {
return demandManageDao.save(myDemand2);
}
}
DAO
@Repository
public class DemandManageDAOImpl implements DemandManageDAO {
@Autowired
SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Override
public Long save(Demand myDemand) throws Exception {
return (Long) getCurrectSession().save(myDemand);
}
private Session getCurrectSession() {
return getSessionFactory().getCurrentSession();
}
}
【问题讨论】:
-
-
知道了。实际上,我链接到的帖子确实提到了使用 autowire 来获取会话工厂。那并摆脱当前的会话上下文线程设置。那并注意堆栈跟踪是哪个事务边界导致的,是否没有活动的休眠会话或其他什么。
标签: java spring hibernate orm transactions