【问题标题】:How do you use Spring Data JPA without Transaction?如何在没有事务的情况下使用 Spring Data JPA?
【发布时间】:2014-08-21 02:38:44
【问题描述】:

我正在尝试使用 Spring Data JPA 访问 Informix 数据库。数据库本身不支持事务。我们通过 JDBC 访问数据库。当您尝试执行任何事务性操作时,Informix 的 JDBC 驱动程序将抛出错误。 getAutoCommit 返回 true,设置为 false 会抛出错误

遗留代码使用 HibernateTemplate 来访问 Informix。服务方法没有任何事务注释

我正在开发一个访问相同数据库的新项目,我想尝试使用 Spring Data。因为,我想继续使用 ORM 层,所以我尝试连接 Spring Data JPA。

所以,我的初始配置是

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="datasource"/>
  <property name="packagesToScan" value="org.company.project.business"/>
  <property name="jpaVendorAdapter">
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

     </bean>
  </property>
  <property name="jpaProperties">
     <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.InformixDialect</prop>
        <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
        <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
        <prop key="hibernate.current_session_context_class">thread</prop>
        <prop key="hibernate.connection.autocommit">false</prop>    
        <prop key="hibernate.jdbc.use_get_generated_keys">true</prop>
        <prop key="hibernate.order_updates">true</prop>
        <prop key="hibernate.generate_statistics">true</prop>
        <prop key="hibernate.connection.release_mode">after_transaction</prop>
     </props>
  </property>
</bean>
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
     destroy-method="close" depends-on="c3p0InformixConnectionCustomizer">
  <constructor-arg type="java.lang.String" value="database"/>
  <property name="driverClass" value="com.informix.jdbc.IfxDriver"/>
  <property name="jdbcUrl" value="${database.jdbc.url}"/>
  <property name="user" value="${database.jdbc.user}"/>
  <property name="password" value="${database.jdbc.password}"/>
</bean>



<bean id="persistenceExceptionTranslationPostProcessor"
     class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<jpa:repositories base-package="org.company.project.respository" entity-manager-factory-ref="emf"/>

不幸的是,Spring 数据抱怨我需要一个事务管理器。但是,我不需要事务管理器!我什至不需要交易

所以,为了大便和咯咯笑,我宣布了 Jpa 事务管理器

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
      <property name="entityManagerFactory" ref="emf"/>
</bean>

显然,Informix 驱动程序开始抱怨不支持事务

所以,问题是我如何告诉 Spring Data 不要使用事务拦截器?我调试了一些调用,所有对 SimpleJPARepository 的调用都连接了 4 个拦截器。其中之一是 TransactionInterceptor。有没有办法告诉 Spring 数据不要连接拦截器?


我最终做的是实现一个 NullTransactionManager。基本上,一个什么都不做的事务管理器......只是为了给 Spring Data 一些东西来咀嚼。有没有更好的办法?我宁愿告诉创建存储库的工厂不要连接拦截器。

public class NullTransactionManager implements PlatformTransactionManager
{
    public NullTransactionManager()
    {
        super();
    }

    public TransactionStatus getTransaction(TransactionDefinition pDefinition) throws TransactionException
    {
        // return a transaction status that doesn't do antyhing
        return new TransactionStatus() {
            public boolean isNewTransaction()
            {
                return false;
            }

            public boolean hasSavepoint()
            {
                return false;
            }

            public void setRollbackOnly()
            {
            }

            public boolean isRollbackOnly()
            {
                return false;
            }

            public void flush()
            {
            }

            public boolean isCompleted()
            {
                return false;
            }

            public Object createSavepoint()
            {
                return null;
            }

            public void rollbackToSavepoint(Object pSavepoint)
            {
            }

            public void releaseSavepoint(Object pSavepoint)
            {
            }
        };
    }

    public void commit(TransactionStatus pStatus) throws TransactionException
    {
        //do nothing
    }

    public void rollback(TransactionStatus pStatus) throws TransactionException
    {
        //do nothing
    }
}

【问题讨论】:

  • 什么样的数据库不支持事务? :)I'm assuming this is your case。所以你正在运行一个非ANSI、非日志数据库?只是出于好奇,以这种方式配置 Informix 数据库有什么好处?
  • 如果您使用 EclipseLink 作为您的 JPA 提供程序,you could've used this solution
  • 您是否尝试过将hibernate.connection.autocommit 用作described here
  • 数据库是旧数据库。我们并不是故意选择使用一个 15 年前的数据库。我们正试图摆脱 Informix,但由于系统太大,我们必须采取分阶段的方法。这意味着我们将不得不使用 Informix,直到我们完成将所有内容移至 JPA...我认为 EclipseLink 不会有帮助,因为它是 JPA 事务管理器设置自动提交。正如我在 OP 中提到的那样,我已将 hibernate.connection.autocommit 设置为 false。没用
  • 啊,好吧,抱歉,我没有仔细阅读您的jpaProperties。似乎你的NullTransactionManager 可能是唯一的方法......

标签: java hibernate jpa informix spring-data-jpa


【解决方案1】:

根据定义,您不能在没有事务的情况下通过 JPA 持久化对象。规范的第 7.9.1 节明确指出,EntityManager.persist(…)….merge(…) 之类的方法需要进行事务处理。

【讨论】:

    猜你喜欢
    • 2019-08-19
    • 2018-07-12
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    • 2019-01-26
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多