Spring + HibernateTemplate + AOP用于事务管理不起作用

时间:2017-04-30 10:37:24

标签: java spring hibernate transactions spring-transactions

我使用简单的“helloWorld”ish应用程序来学习使用AOP的Spring,Hibernate和事务管理。但是没有按预期工作。我在事务管理中遇到异常。详情如下: -

Spring version 4.3.8
Hibernate version 5.2.10
HSQL DB version 2.3.4 

Spring.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

<!-- Enable Annotation based Declarative Transaction Management -->
<tx:annotation-driven proxy-target-class="true" mode="aspectj"
    transaction-manager="transactionManager" />

<!-- THIS IS COMMENTED. Without commenting same result. I TRIED USING HibernateTransactionManager. still got same result.  -->
    <!--
<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean> -->


<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
    <property name="url" value="jdbc:hsqldb:file:C:/ProjectRelated/softwares/hsqldb-2.3.4/hsqldb/data/FirstFile"/>
    <property name="username" value="sa"/>
    <property name="password" value="sys"/>
</bean>

<bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" >
    <array>
        <value>com.kaushik.winnersoft.data</value>
    </array>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
        </props>
    </property>
</bean>

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
    <property name="sessionFactory" ref="mySessionFactory"/>
</bean>


<bean id="customerDAO" class="com.kaushik.winnersoft.dao.CustomerDAOImpl">
    <property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>

<bean id="customerManager" class="com.kaushik.winnersoft.CustomerManagerImpl">
    <property name="customerDAO" ref="customerDAO"></property>
</bean>

DAOImpl类是

public class CustomerDAOImpl implements CustomerDAO {

private HibernateTemplate hibernateTemplate;

public HibernateTemplate getHibernateTemplate() {
    return hibernateTemplate;
}

public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
}

@Override
@Transactional
public void create(Customer customer) {
    System.out.println("in  dao creating");
    hibernateTemplate.save(customer);
    System.out.println("in  dao creating done");
}

我得到如下输出

Doing
in  dao creating
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
at org.springframework.orm.hibernate5.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1165)
at org.springframework.orm.hibernate5.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:643)
at org.springframework.orm.hibernate5.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:640)
at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:359)
at org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:326)
at org.springframework.orm.hibernate5.HibernateTemplate.save(HibernateTemplate.java:640)
at com.kaushik.winnersoft.dao.CustomerDAOImpl.create(CustomerDAOImpl.java:27)
at com.kaushik.winnersoft.CustomerManagerImpl.createCustomer(CustomerManagerImpl.java:20)
at com.kaushik.winnersoft.SpringTest.main(SpringTest.java:14)

答案

基于M. Denium在下面给出的评论;我做了以下更改并且工作正常。

1)使用HibernateTransactionManager而不是DataSourceTransactionManager

<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory" />
</bean> 

2)在删除模式=“aspectj” 所以它看起来像

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />

1 个答案:

答案 0 :(得分:1)

我发现您的配置存在问题

  1. 您没有使用正确的PlatformTransactionManager
  2. 除非您使用加载或编译时编织,否则我怀疑mode="aspectj"是否正确。
  3. 首先,您需要使用支持持久性技术的PlatformTransactionManager,因为您使用的是Hibernate 5,您需要使用org.springframework.orm.hibernate5.HibernateTransactionManager而不是DataSourceTransactionManager。 (后者适用于仅执行普通JDBC事务的应用程序)。

    <tx:annotation-driven />移除mode="aspectj"因为我怀疑你实际上并没有使用完整的AspectJ,而是依靠普通的Spring来为你做这件事。

    专家提示:而不是使用自{Hibernate 3.0.1以后不再推荐的HibernateTemplate,而是使用SessionFactory代替getCurrentSession。这将允许您编写简单的Hibernate daos。正如reference guide中所述。