34
34
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Eclipse
35
35
* Persistence Services (EclipseLink). Compatible with EclipseLink 3.0/4.0.
36
36
*
37
- * <p>By default, this class acquires an early EclipseLink transaction with an early
38
- * JDBC Connection for non-read-only transactions. This allows for mixing JDBC and
39
- * JPA/EclipseLink operations in the same transaction, with cross visibility of
37
+ * <p>By default, this dialect acquires an early EclipseLink transaction with an
38
+ * early JDBC Connection for non-read-only transactions. This allows for mixing
39
+ * JDBC and JPA operations in the same transaction, with cross visibility of
40
40
* their impact. If this is not needed, set the "lazyDatabaseTransaction" flag to
41
41
* {@code true} or consistently declare all affected transactions as read-only.
42
42
* As of Spring 4.1.2, this will reliably avoid early JDBC Connection retrieval
43
43
* and therefore keep EclipseLink in shared cache mode.
44
44
*
45
+ * <p><b>NOTE: This dialect supports custom isolation levels with limitations.</b>
46
+ * Consistent isolation level handling is only guaranteed when all Spring transaction
47
+ * definitions specify a concrete isolation level, and as of 6.0.10 also when using
48
+ * the default isolation level with non-readOnly and non-lazy transactions. See the
49
+ * {@link #setLazyDatabaseTransaction "lazyDatabaseTransaction" javadoc} for details.
50
+ *
45
51
* @author Juergen Hoeller
46
52
* @since 2.5.2
47
53
* @see #setLazyDatabaseTransaction
@@ -65,7 +71,16 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect {
65
71
* even for non-read-only transactions, allowing access to EclipseLink's
66
72
* shared cache and following EclipseLink's connection mode configuration,
67
73
* assuming that isolation and visibility at the JDBC level are less important.
74
+ * <p><b>NOTE: Lazy database transactions are not guaranteed to work reliably
75
+ * in combination with custom isolation levels. Use read-only as well as this
76
+ * lazy flag with care. If other transactions use custom isolation levels,
77
+ * it is not recommended to use read-only and lazy transactions at all.</b>
78
+ * Otherwise, you may see non-default isolation levels used during read-only
79
+ * or lazy access. If this is not acceptable, don't use read-only and lazy
80
+ * next to custom isolation levels in potentially concurrent transactions.
68
81
* @see org.eclipse.persistence.sessions.UnitOfWork#beginEarlyTransaction()
82
+ * @see TransactionDefinition#isReadOnly()
83
+ * @see TransactionDefinition#getIsolationLevel()
69
84
*/
70
85
public void setLazyDatabaseTransaction (boolean lazyDatabaseTransaction ) {
71
86
this .lazyDatabaseTransaction = lazyDatabaseTransaction ;
@@ -83,7 +98,8 @@ public Object beginTransaction(EntityManager entityManager, TransactionDefinitio
83
98
// (since Spring 4.1.2 / revised in 5.3.28)
84
99
UnitOfWork uow = entityManager .unwrap (UnitOfWork .class );
85
100
DatabaseLogin databaseLogin = uow .getLogin ();
86
- // Synchronize on shared DatabaseLogin instance (-> concurrent transactions)
101
+ // Synchronize on shared DatabaseLogin instance for consistent isolation level
102
+ // set and reset in case of concurrent transactions with different isolation.
87
103
synchronized (databaseLogin ) {
88
104
int originalIsolationLevel = databaseLogin .getTransactionIsolation ();
89
105
// Apply current isolation level value, if necessary.
@@ -101,13 +117,23 @@ public Object beginTransaction(EntityManager entityManager, TransactionDefinitio
101
117
}
102
118
}
103
119
}
120
+ else if (!definition .isReadOnly () && !this .lazyDatabaseTransaction ) {
121
+ // Begin an early transaction to force EclipseLink to get a JDBC Connection
122
+ // so that Spring can manage transactions with JDBC as well as EclipseLink.
123
+ UnitOfWork uow = entityManager .unwrap (UnitOfWork .class );
124
+ DatabaseLogin databaseLogin = uow .getLogin ();
125
+ // Synchronize on shared DatabaseLogin instance for consistently picking up
126
+ // the default isolation level even in case of concurrent transactions with
127
+ // a custom isolation level (see above), as of 6.0.10
128
+ synchronized (databaseLogin ) {
129
+ entityManager .getTransaction ().begin ();
130
+ uow .beginEarlyTransaction ();
131
+ entityManager .unwrap (Connection .class );
132
+ }
133
+ }
104
134
else {
135
+ // Regular transaction begin with lazy database transaction.
105
136
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
- }
111
137
}
112
138
113
139
return null ;
0 commit comments