diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaDialect.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaDialect.java index 7fefab90c24..4a952a4d1ac 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaDialect.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaDialect.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import java.sql.SQLException; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceException; +import org.eclipse.persistence.sessions.DatabaseLogin; import org.eclipse.persistence.sessions.UnitOfWork; import org.springframework.jdbc.datasource.ConnectionHandle; @@ -31,8 +32,7 @@ import org.springframework.transaction.TransactionException; /** * {@link org.springframework.orm.jpa.JpaDialect} implementation for Eclipse - * Persistence Services (EclipseLink). Developed and tested against EclipseLink 2.7; - * backwards-compatible with EclipseLink 2.5 and 2.6 at runtime. + * Persistence Services (EclipseLink). Compatible with EclipseLink 3.0/4.0. * *

By default, this class acquires an early EclipseLink transaction with an early * JDBC Connection for non-read-only transactions. This allows for mixing JDBC and @@ -77,22 +77,40 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect { public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) throws PersistenceException, SQLException, TransactionException { - if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { + int currentIsolationLevel = definition.getIsolationLevel(); + if (currentIsolationLevel != TransactionDefinition.ISOLATION_DEFAULT) { // Pass custom isolation level on to EclipseLink's DatabaseLogin configuration - // (since Spring 4.1.2) + // (since Spring 4.1.2 / revised in 5.3.28) UnitOfWork uow = entityManager.unwrap(UnitOfWork.class); - uow.getLogin().setTransactionIsolation(definition.getIsolationLevel()); + DatabaseLogin databaseLogin = uow.getLogin(); + // Synchronize on shared DatabaseLogin instance (-> concurrent transactions) + synchronized (databaseLogin) { + int originalIsolationLevel = databaseLogin.getTransactionIsolation(); + // Apply current isolation level value, if necessary. + if (currentIsolationLevel != originalIsolationLevel) { + databaseLogin.setTransactionIsolation(currentIsolationLevel); + } + // Transaction begin including enforced JDBC Connection access + // (picking up current isolation level from DatabaseLogin) + entityManager.getTransaction().begin(); + uow.beginEarlyTransaction(); + entityManager.unwrap(Connection.class); + // Restore original isolation level value, if necessary. + if (currentIsolationLevel != originalIsolationLevel) { + databaseLogin.setTransactionIsolation(originalIsolationLevel); + } + } } - - entityManager.getTransaction().begin(); - - if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { - // Begin an early transaction to force EclipseLink to get a JDBC Connection - // so that Spring can manage transactions with JDBC as well as EclipseLink. - entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); + else { + entityManager.getTransaction().begin(); + if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { + // Begin an early transaction to force EclipseLink to get a JDBC Connection + // so that Spring can manage transactions with JDBC as well as EclipseLink. + entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); + } } - return null; + return entityManager; } @Override diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java index d26bd1e67b5..4cbe6c71d7e 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,8 +30,7 @@ import org.springframework.lang.Nullable; /** * {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Eclipse - * Persistence Services (EclipseLink). Developed and tested against EclipseLink 2.7; - * backwards-compatible with EclipseLink 2.5 and 2.6 at runtime. + * Persistence Services (EclipseLink). Compatible with EclipseLink 3.0/4.0. * *

Exposes EclipseLink's persistence provider and EntityManager extension interface, * and adapts {@link AbstractJpaVendorAdapter}'s common configuration settings.