Spring управляемые транзакции, EclipseLink JPA, пользовательский уровень изоляции

Я подозреваю, что это смущает, и я делаю это неправильно ужасным образом, но, пожалуйста, потерпите меня.

у меня есть приложение Spring с Spring-управляемыми транзакциями. Он использует EclipseLink JPA. У меня есть метод, который делает findByNativeQuery() затем merge(). Мне нужно, чтобы это произошло на реальном уровне изоляции последовательных транзакций. Я попытался добавить @Transactional(isolation=Isolation.SERIALIZABLE)

Это не работает, потому что org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect#beginTransaction не поддерживает уровень изоляции транзакций, кроме уровня по умолчанию. Так затем я попытался добраться до внутренних частей Elcipselink и начать / завершить мои собственные транзакции, но затем я получаю ошибку:

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

что, конечно, имеет смысл... но что мне делать??

3 ответов


я попробовал это, но я не совсем уверен в решении. Я взял код из этот блог и адаптировал его для 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;
    }
}

Я вижу, что СЕРИАЛИЗУЕМАЯ изоляция регистрируется при инициализации транзакции, но это необходимо проверить должным образом, чтобы подтвердить, что она работает.


поддержка пользовательского уровня изоляции была добавлена весной 4.1.2 в EclipseLinkJpaDialect


вы можете обратиться

"для достижения сериализуемой изоляции транзакций с помощью EclipseLink мы рекомендуем использовать изолированный сеанс клиента следующим образом:

настройте изоляцию транзакций базы данных как сериализуемую. Настройка объектов как изолированных (см. настройка изоляции кэша на уровне проекта или настройка изоляции кэша на уровне дескриптора). Используйте метод UnitOfWork beginTransactionEarly (см. Метод Unit of Work beginTransactionEarly). Если вы обеспокоены только аспектом записи сериализуемой, оптимистичной блокировки достаточно."

at http://docs.oracle.com/middleware/1212/toplink/OTLCG/cache.htm или пройти http://docs.oracle.com/middleware/1212/toplink/OTLCG/cache.htm если какой-либо из уровней изоляции соответствует вашему требованию