【问题标题】:Spring + HibernateTemplate + AOP for transaction mamangement not working用于事务管理的 Spring + HibernateTemplate + AOP 不起作用
【发布时间】:2017-04-30 10:37:24
【问题描述】:

我正在使用简单的“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" />

【问题讨论】:

  • 您使用了错误的事务管理器。使用适合您的持久层的那个。您正在使用休眠,所以使用HibernateTransactionManager 而不是DataSourceTransactionManager。我建议不要使用自 Hibernate 3.0.1(或引入 Hibernate 上下文会话)以来不再推荐的 HibernateTemplate
  • DataSourceTransactionManager 部分实际上是在上面的 XML 中注释的。很抱歉造成混乱。我现在把它从问题中删除了。我仍然尝试配置 HibernateTransactionManager。还是一样的错误。
  • 并从tx:annotation-driven 中删除mode="aspectj",除非你真的在使用我非常怀疑的加载或编译时编织。尽管如此,您仍然需要使用适当的事务管理器。
  • 哇,好用。
  • @M.Deinum 能否请您在上面的 commnet 中添加您的两个建议作为答案,以便我接受并给予您信任。

标签: java spring hibernate transactions spring-transactions


【解决方案1】:

我发现你的配置有问题

  1. 您没有使用正确的PlatformTransactionManager
  2. 除非您使用加载或编译时编织,否则我怀疑mode="aspectj" 是否真的正确。

首先你需要使用支持你的持久化技术的PlatformTransactionManager,因为你使用的是Hibernate 5,你需要使用org.springframework.orm.hibernate5.HibernateTransactionManager而不是DataSourceTransactionManager。 (后者适用于仅执行普通 JDBC 事务的应用程序)。

&lt;tx:annotation-driven /&gt; 中删除mode="aspectj",因为我怀疑您实际上并没有使用成熟的AspectJ,而是依靠普通的Spring 为您执行此操作。

专业提示:不要使用自 Hibernate 3.0.1 以来不再推荐的 HibernateTemplate,而是使用普通的 SessionFactorygetCurrentSession。这将允许您编写简单的 Hibernate daos。正如reference guide 中所建议的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2011-04-12
    • 2013-04-19
    • 2018-09-10
    相关资源
    最近更新 更多