java spring jpa transactions eclipselink

java - Transacciones gestionadas de primavera, EclipseLink JPA, nivel de aislamiento personalizado



spring transactions (3)

Sospecho que este es embarazoso y lo estoy haciendo mal de una manera terrible, pero por favor tengan paciencia conmigo.

Tengo una aplicación Spring con transacciones gestionadas por Spring. Utiliza EclipseLink JPA. Tengo un método que hace un findByNativeQuery() seguido de un merge() . Necesito que esto suceda en un nivel de aislamiento de transacción SERIAL real. Intenté agregar @Transactional(isolation=Isolation.SERIALIZABLE)

Esto no funciona porque org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect#beginTransaction no admite ningún nivel de aislamiento de transacción, sino el predeterminado. Así que intenté acceder a los componentes internos de UnitOfWork de ElcipseLink y comencé / cerré mis propias transacciones, pero luego recibí un error:

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

Lo cual por supuesto tiene sentido ... ¿pero qué hago?


El soporte para el nivel de aislamiento personalizado se agregó en Spring 4.1.2 a EclipseLinkJpaDialect


He intentado esto, pero no estoy completamente seguro de la solución. Tomé el código de este blog y lo adapté para EclipseLink. Aquí está el código:

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; } }

Veo que se registra el aislamiento SERIALIZABLE cuando se inicia la transacción, pero esto debe probarse correctamente para confirmar que funciona.


Puedes referirte

"Para lograr el aislamiento de transacciones serializable con EclipseLink, recomendamos que use una sesión de cliente aislada de la siguiente manera:

Configure el aislamiento de transacción de la base de datos como serializable. Configure los objetos como aislados (consulte Configurar el aislamiento de caché en el nivel de proyecto o Configurar el aislamiento de caché en el nivel de descriptor). Use el método UnitOfWork beginTransactionEarly (consulte el Método de unidad de trabajo beginTransactionEarly). Si solo le preocupa el aspecto de escritura de bloqueo serializable y optimista, es suficiente ".

en http://docs.oracle.com/middleware/1212/toplink/OTLCG/cache.htm o vaya a http://docs.oracle.com/middleware/1212/toplink/OTLCG/cache.htm si hay aislamiento nivel cumple con su requisito