Как вы используете Spring Data JPA без транзакций?

Я пытаюсь использовать Spring Data JPA для доступа к базе данных Informix. Сама база данных не поддерживает транзакции. Мы получаем доступ к базе данных через JDBC. Драйвер JDBC для Informix выдаст ошибку, когда вы попытаетесь сделать что-нибудь транзакционное. 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
    }
}

1 ответ

Вы не можете - по определению - сохранить объекты через JPA без транзакции. В разделе 7.9.1 спецификации четко указано, что такие методы, как EntityManager.persist(…) а также ….merge(…) требовать транзакции для выполнения.

Другие вопросы по тегам