HibernateException:没有活动事务,save无效

时间:2014-06-23 19:11:24

标签: java spring hibernate orm transactions

所以我彻底地完成了 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

这似乎是以前版本的常规。我可以通过开会和开始交易来解决这个问题,但我不想这样做。

上下文: applicationContext.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>

datasource.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"));
    }
}

serviceImpl

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

1 个答案:

答案 0 :(得分:1)

您不能对事务使用自动提交,而是需要由事务管理器管理连接,因此请删除以下行:

<prop key="hibernate.connection.autocommit">true</prop>

您也可以添加:

<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property><prop