|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2018 the original author or authors. |
| 2 | + * Copyright 2002-2023 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
21 | 21 |
|
22 | 22 | import jakarta.persistence.EntityManager;
|
23 | 23 | import jakarta.persistence.PersistenceException;
|
| 24 | +import org.eclipse.persistence.sessions.DatabaseLogin; |
24 | 25 | import org.eclipse.persistence.sessions.UnitOfWork;
|
25 | 26 |
|
26 | 27 | import org.springframework.jdbc.datasource.ConnectionHandle;
|
|
31 | 32 |
|
32 | 33 | /**
|
33 | 34 | * {@link org.springframework.orm.jpa.JpaDialect} implementation for Eclipse
|
34 |
| - * Persistence Services (EclipseLink). Developed and tested against EclipseLink 2.7; |
35 |
| - * backwards-compatible with EclipseLink 2.5 and 2.6 at runtime. |
| 35 | + * Persistence Services (EclipseLink). Compatible with EclipseLink 3.0/4.0. |
36 | 36 | *
|
37 | 37 | * <p>By default, this class acquires an early EclipseLink transaction with an early
|
38 | 38 | * JDBC Connection for non-read-only transactions. This allows for mixing JDBC and
|
@@ -77,22 +77,40 @@ public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) {
|
77 | 77 | public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition)
|
78 | 78 | throws PersistenceException, SQLException, TransactionException {
|
79 | 79 |
|
80 |
| - if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { |
| 80 | + int currentIsolationLevel = definition.getIsolationLevel(); |
| 81 | + if (currentIsolationLevel != TransactionDefinition.ISOLATION_DEFAULT) { |
81 | 82 | // Pass custom isolation level on to EclipseLink's DatabaseLogin configuration
|
82 |
| - // (since Spring 4.1.2) |
| 83 | + // (since Spring 4.1.2 / revised in 5.3.28) |
83 | 84 | UnitOfWork uow = entityManager.unwrap(UnitOfWork.class);
|
84 |
| - uow.getLogin().setTransactionIsolation(definition.getIsolationLevel()); |
| 85 | + DatabaseLogin databaseLogin = uow.getLogin(); |
| 86 | + // Synchronize on shared DatabaseLogin instance (-> concurrent transactions) |
| 87 | + synchronized (databaseLogin) { |
| 88 | + int originalIsolationLevel = databaseLogin.getTransactionIsolation(); |
| 89 | + // Apply current isolation level value, if necessary. |
| 90 | + if (currentIsolationLevel != originalIsolationLevel) { |
| 91 | + databaseLogin.setTransactionIsolation(currentIsolationLevel); |
| 92 | + } |
| 93 | + // Transaction begin including enforced JDBC Connection access |
| 94 | + // (picking up current isolation level from DatabaseLogin) |
| 95 | + entityManager.getTransaction().begin(); |
| 96 | + uow.beginEarlyTransaction(); |
| 97 | + entityManager.unwrap(Connection.class); |
| 98 | + // Restore original isolation level value, if necessary. |
| 99 | + if (currentIsolationLevel != originalIsolationLevel) { |
| 100 | + databaseLogin.setTransactionIsolation(originalIsolationLevel); |
| 101 | + } |
| 102 | + } |
85 | 103 | }
|
86 |
| - |
87 |
| - entityManager.getTransaction().begin(); |
88 |
| - |
89 |
| - if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { |
90 |
| - // Begin an early transaction to force EclipseLink to get a JDBC Connection |
91 |
| - // so that Spring can manage transactions with JDBC as well as EclipseLink. |
92 |
| - entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); |
| 104 | + else { |
| 105 | + entityManager.getTransaction().begin(); |
| 106 | + if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { |
| 107 | + // Begin an early transaction to force EclipseLink to get a JDBC Connection |
| 108 | + // so that Spring can manage transactions with JDBC as well as EclipseLink. |
| 109 | + entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); |
| 110 | + } |
93 | 111 | }
|
94 | 112 |
|
95 |
| - return null; |
| 113 | + return entityManager; |
96 | 114 | }
|
97 | 115 |
|
98 | 116 | @Override
|
|
0 commit comments