24
24
import org .eclipse .persistence .sessions .UnitOfWork ;
25
25
26
26
import org .springframework .jdbc .datasource .ConnectionHandle ;
27
- import org .springframework .jdbc .datasource .SimpleConnectionHandle ;
28
27
import org .springframework .orm .jpa .DefaultJpaDialect ;
29
28
import org .springframework .transaction .TransactionDefinition ;
30
29
import org .springframework .transaction .TransactionException ;
33
32
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Eclipse
34
33
* Persistence Services (EclipseLink). Developed and tested against EclipseLink 2.4.
35
34
*
36
- * <p>By default, this class acquires a EclipseLink transaction to get the JDBC Connection
37
- * early. This allows mixing JDBC and JPA/EclipseLink operations in the same transaction.
38
- * In some cases, this eager acquisition of a transaction/connection may impact
39
- * scalability. In that case, set the "lazyDatabaseTransaction" flag to true if you
40
- * do not require mixing JDBC and JPA operations in the same transaction. Otherwise,
41
- * use a {@link org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy}
42
- * to ensure that the cost of connection acquisition is near zero until code actually
43
- * needs a JDBC Connection.
35
+ * <p>By default, this class acquires an early EclipseLink transaction with an early
36
+ * JDBC Connection for non-read-only transactions. This allows for mixing JDBC and
37
+ * JPA/EclipseLink operations in the same transaction, with cross visibility of
38
+ * their impact. If this is not needed, set the "lazyDatabaseTransaction" flag to
39
+ * {@code true} or consistently declare all affected transactions as read-only.
40
+ * As of Spring 4.1.2, this will reliably avoid early JDBC Connection retrieval
41
+ * and therefore keep EclipseLink in shared cache mode.
44
42
*
45
43
* @author Juergen Hoeller
46
44
* @since 2.5.2
@@ -78,6 +76,7 @@ public Object beginTransaction(EntityManager entityManager, TransactionDefinitio
78
76
79
77
if (definition .getIsolationLevel () != TransactionDefinition .ISOLATION_DEFAULT ) {
80
78
// Pass custom isolation level on to EclipseLink's DatabaseLogin configuration
79
+ // (since Spring 4.1.2)
81
80
uow .getLogin ().setTransactionIsolation (definition .getIsolationLevel ());
82
81
}
83
82
@@ -96,8 +95,41 @@ public Object beginTransaction(EntityManager entityManager, TransactionDefinitio
96
95
public ConnectionHandle getJdbcConnection (EntityManager entityManager , boolean readOnly )
97
96
throws PersistenceException , SQLException {
98
97
99
- Connection con = entityManager .unwrap (Connection .class );
100
- return (con != null ? new SimpleConnectionHandle (con ) : null );
98
+ // As of Spring 4.1.2, we're using a custom ConnectionHandle for lazy retrieval
99
+ // of the underlying Connection (allowing for deferred internal transaction begin
100
+ // within the EclipseLink EntityManager)
101
+ return new EclipseLinkConnectionHandle (entityManager );
102
+ }
103
+
104
+
105
+ /**
106
+ * {@link ConnectionHandle} implementation that lazily fetches an
107
+ * EclipseLink-provided Connection on the first {@code getConnection} call -
108
+ * which may never come if no application code requests a JDBC Connection.
109
+ * This is useful to defer the early transaction begin that obtaining a
110
+ * JDBC Connection implies within an EclipseLink EntityManager.
111
+ */
112
+ private static class EclipseLinkConnectionHandle implements ConnectionHandle {
113
+
114
+ private final EntityManager entityManager ;
115
+
116
+ private Connection connection ;
117
+
118
+ public EclipseLinkConnectionHandle (EntityManager entityManager ) {
119
+ this .entityManager = entityManager ;
120
+ }
121
+
122
+ @ Override
123
+ public Connection getConnection () {
124
+ if (this .connection == null ) {
125
+ this .connection = this .entityManager .unwrap (Connection .class );
126
+ }
127
+ return this .connection ;
128
+ }
129
+
130
+ @ Override
131
+ public void releaseConnection (Connection con ) {
132
+ }
101
133
}
102
134
103
135
}
0 commit comments