Java Spring管理事务、EclipseLink JPA、自定义隔离级别

Java Spring管理事务、EclipseLink JPA、自定义隔离级别,java,spring,jpa,transactions,eclipselink,Java,Spring,Jpa,Transactions,Eclipselink,我怀疑这件事令人尴尬,我做错了,但请容忍我 我有一个带有Spring管理事务的Spring应用程序。 它使用EclipselinkJPA。 我有一个方法,它先执行findByNativeQuery(),然后执行merge()。我需要在真正的串行事务隔离级别中实现这一点。 我试着加上 @Transactional(隔离=隔离.可序列化) 这不起作用,因为org.springframework.orm.jpa.vendor.eclipseelinkjpadialect#beginTransactio

我怀疑这件事令人尴尬,我做错了,但请容忍我

我有一个带有Spring管理事务的Spring应用程序。 它使用EclipselinkJPA。 我有一个方法,它先执行
findByNativeQuery()
,然后执行
merge()
。我需要在真正的串行事务隔离级别中实现这一点。 我试着加上
@Transactional(隔离=隔离.可序列化)

这不起作用,因为
org.springframework.orm.jpa.vendor.eclipseelinkjpadialect#beginTransaction
不支持任何事务隔离级别,但支持默认事务隔离级别。 因此,我尝试访问ElcipseLink的UnitOfWork内部并开始/提交我自己的事务,但随后出现了一个错误:

"java.lang.IllegalStateException : Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead

这当然有道理。。。但是我该怎么办呢?

我已经尝试过了,但我不完全确定解决方案。我已经从EclipseLink中获取了代码并对其进行了修改。代码如下:

package com.byteslounge.spring.tx.dialect;

import java.sql.SQLException;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;

import org.eclipse.persistence.sessions.UnitOfWork;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;

public class CustomEclipseLinkJpaDialect extends EclipseLinkJpaDialect {

    private static final long serialVersionUID = 1L;

    private boolean lazyDatabaseTransaction = false;

    @Override
    public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) {
        this.lazyDatabaseTransaction = lazyDatabaseTransaction;
    }

    @Override
    public Object beginTransaction(final EntityManager entityManager,
            final TransactionDefinition definition)
            throws PersistenceException, SQLException, TransactionException {

        UnitOfWork uow = (UnitOfWork) getSession(entityManager);
        uow.getLogin().setTransactionIsolation(definition.getIsolationLevel());

        entityManager.getTransaction().begin();
        if (!definition.isReadOnly() && !lazyDatabaseTransaction) {
            uow.beginEarlyTransaction();
        }

        return null;
    }
}
我看到事务启动时会记录可序列化隔离,但这需要正确测试以确认其工作。

您可以参考

“为了使用EclipseLink实现可序列化事务隔离,我们建议您使用如下隔离的客户端会话:

将数据库事务隔离配置为可序列化。 将对象配置为隔离对象(请参阅在项目级别配置缓存隔离或在描述符级别配置缓存隔离)。 使用工作单元方法beginTransactionEarly(请参阅工作单元方法beginTransactionEarly)。 如果您只关心serializable的写入方面,乐观锁定就足够了。”

到达或通过
如果任何隔离级别满足您的要求

请查看Spring 4.1.2中添加的自定义隔离级别支持。我自己也没有试过,但看起来是个不错的开始。我认为JPA不支持自定义隔离级别。这是JPA的限制,而不是Spring。它可能需要实现定制的JPadiolect。我已经调试了我的代码,进入了
JpaTransactionManager.doBegin()
方法,并检查了
ConnectionHandle
以查找实际的MySQL
com.MySQL.jdbc.JDBC4Connection
实例。实际使用的连接实际上使用了该方法的隔离级别集(javax.sql.connection.TRANSACTION_SERIALIZABLE)。我们还没有时间对其进行测试,但我想我会给予奖励,因为这是投入大量精力的唯一答案。未来的读者要当心——这个公认的答案还没有经过正确性评估。我对此进行了尝试。请教育我。。如果事务定义为“需要传播”且“隔离”可序列化,则会使从另一个线程创建的所有事务都处于等待状态(如果已在运行具有相同定义的事务),这是否适用?如果我想实现它,需要调整什么?对于Spring 3.2.13的
PROPAGATION\u REQUIRED
。谢谢