|
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.
|
|
22 | 22 | import javax.persistence.EntityManager;
|
23 | 23 | import javax.persistence.PersistenceException;
|
24 | 24 |
|
| 25 | +import org.eclipse.persistence.sessions.DatabaseLogin; |
25 | 26 | import org.eclipse.persistence.sessions.UnitOfWork;
|
26 | 27 |
|
27 | 28 | import org.springframework.jdbc.datasource.ConnectionHandle;
|
@@ -78,19 +79,37 @@ public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) {
|
78 | 79 | public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition)
|
79 | 80 | throws PersistenceException, SQLException, TransactionException {
|
80 | 81 |
|
81 |
| - if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { |
| 82 | + int currentIsolationLevel = definition.getIsolationLevel(); |
| 83 | + if (currentIsolationLevel != TransactionDefinition.ISOLATION_DEFAULT) { |
82 | 84 | // Pass custom isolation level on to EclipseLink's DatabaseLogin configuration
|
83 |
| - // (since Spring 4.1.2) |
| 85 | + // (since Spring 4.1.2 / revised in 5.3.28) |
84 | 86 | UnitOfWork uow = entityManager.unwrap(UnitOfWork.class);
|
85 |
| - uow.getLogin().setTransactionIsolation(definition.getIsolationLevel()); |
| 87 | + DatabaseLogin databaseLogin = uow.getLogin(); |
| 88 | + // Synchronize on shared DatabaseLogin instance (-> concurrent transactions) |
| 89 | + synchronized (databaseLogin) { |
| 90 | + int originalIsolationLevel = databaseLogin.getTransactionIsolation(); |
| 91 | + // Apply current isolation level value, if necessary. |
| 92 | + if (currentIsolationLevel != originalIsolationLevel) { |
| 93 | + databaseLogin.setTransactionIsolation(currentIsolationLevel); |
| 94 | + } |
| 95 | + // Transaction begin including enforced JDBC Connection access |
| 96 | + // (picking up current isolation level from DatabaseLogin) |
| 97 | + entityManager.getTransaction().begin(); |
| 98 | + uow.beginEarlyTransaction(); |
| 99 | + entityManager.unwrap(Connection.class); |
| 100 | + // Restore original isolation level value, if necessary. |
| 101 | + if (currentIsolationLevel != originalIsolationLevel) { |
| 102 | + databaseLogin.setTransactionIsolation(originalIsolationLevel); |
| 103 | + } |
| 104 | + } |
86 | 105 | }
|
87 |
| - |
88 |
| - entityManager.getTransaction().begin(); |
89 |
| - |
90 |
| - if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { |
91 |
| - // Begin an early transaction to force EclipseLink to get a JDBC Connection |
92 |
| - // so that Spring can manage transactions with JDBC as well as EclipseLink. |
93 |
| - entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); |
| 106 | + else { |
| 107 | + entityManager.getTransaction().begin(); |
| 108 | + if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { |
| 109 | + // Begin an early transaction to force EclipseLink to get a JDBC Connection |
| 110 | + // so that Spring can manage transactions with JDBC as well as EclipseLink. |
| 111 | + entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); |
| 112 | + } |
94 | 113 | }
|
95 | 114 |
|
96 | 115 | return null;
|
|
0 commit comments