Как вы используете 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(…)
требовать транзакции для выполнения.