Browse Source

Consistent handling of early setCatalog/setSchema/setHoldability calls

Closes gh-36527
Closes gh-36528
7.0.x
Juergen Hoeller 5 days ago
parent
commit
6cea397bd8
  1. 79
      spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java
  2. 23
      spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java

79
spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java

@ -21,7 +21,6 @@ import java.lang.reflect.InvocationTargetException; @@ -21,7 +21,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
@ -300,13 +299,17 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { @@ -300,13 +299,17 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
private @Nullable String password;
private @Nullable Boolean autoCommit;
private @Nullable String catalog;
private @Nullable Integer transactionIsolation;
private @Nullable String schema;
private @Nullable Integer holdability;
private boolean readOnly = false;
private int holdability = ResultSet.CLOSE_CURSORS_AT_COMMIT;
private @Nullable Integer transactionIsolation;
private @Nullable Boolean autoCommit;
private boolean closed = false;
@ -364,26 +367,34 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { @@ -364,26 +367,34 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
case "toString" -> {
return "Lazy Connection proxy for target DataSource [" + getTargetDataSource() + "]";
}
case "getAutoCommit" -> {
if (this.autoCommit != null) {
return this.autoCommit;
case "getCatalog" -> {
if (this.catalog != null) {
return this.catalog;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
// Else fetch actual Connection and check there.
}
case "setAutoCommit" -> {
this.autoCommit = (Boolean) args[0];
case "setCatalog" -> {
this.catalog = (String) args[0];
return null;
}
case "getTransactionIsolation" -> {
if (this.transactionIsolation != null) {
return this.transactionIsolation;
case "getSchema" -> {
if (this.schema != null) {
return this.schema;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
// Else fetch actual Connection and check there.
}
case "setTransactionIsolation" -> {
this.transactionIsolation = (Integer) args[0];
case "setSchema" -> {
this.schema = (String) args[0];
return null;
}
case "getHoldability" -> {
if (this.holdability != null) {
return this.holdability;
}
// Else fetch actual Connection and check there.
}
case "setHoldability" -> {
this.holdability = (Integer) args[0];
return null;
}
case "isReadOnly" -> {
@ -393,11 +404,26 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { @@ -393,11 +404,26 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
this.readOnly = (Boolean) args[0];
return null;
}
case "getHoldability" -> {
return this.holdability;
case "getTransactionIsolation" -> {
if (this.transactionIsolation != null) {
return this.transactionIsolation;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
}
case "setHoldability" -> {
this.holdability = (Integer) args[0];
case "setTransactionIsolation" -> {
this.transactionIsolation = (Integer) args[0];
return null;
}
case "getAutoCommit" -> {
if (this.autoCommit != null) {
return this.autoCommit;
}
// Else fetch actual Connection and check there,
// because we didn't have a default specified.
}
case "setAutoCommit" -> {
this.autoCommit = (Boolean) args[0];
return null;
}
case "commit", "rollback" -> {
@ -485,6 +511,15 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { @@ -485,6 +511,15 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
// Apply kept transaction settings, if any.
try {
if (this.catalog != null) {
target.setCatalog(this.catalog);
}
if (this.schema != null) {
target.setSchema(this.schema);
}
if (this.holdability != null) {
target.setHoldability(this.holdability);
}
if (this.readOnly && readOnlyDataSource == null) {
DataSourceUtils.setReadOnlyIfPossible(target);
}

23
spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java

@ -19,6 +19,7 @@ package org.springframework.jdbc.datasource; @@ -19,6 +19,7 @@ package org.springframework.jdbc.datasource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
@ -828,14 +829,32 @@ public class DataSourceTransactionManagerTests { @@ -828,14 +829,32 @@ public class DataSourceTransactionManagerTests {
dsProxy.setDefaultAutoCommit(true);
dsProxy.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
dsProxy.afterPropertiesSet();
tm = createTransactionManager(dsProxy);
try (Connection con = dsProxy.getConnection()) {
DelegatingDataSource dsAdapter = new DelegatingDataSource(dsProxy) {
@Override
public Connection getConnection() throws SQLException {
Connection con = super.getConnection();
con.setCatalog("myCatalog");
con.setSchema("mySchema");
con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
return con;
}
};
tm = createTransactionManager(dsAdapter);
try (Connection con = dsAdapter.getConnection()) {
assertThat(con.isReadOnly()).isFalse();
assertThat(con.getCatalog()).isEqualTo("myCatalog");
assertThat(con.getSchema()).isEqualTo("mySchema");
assertThat(con.getHoldability()).isEqualTo(ResultSet.HOLD_CURSORS_OVER_COMMIT);
}
assertTransactionReadOnly(TransactionDefinition.ISOLATION_SERIALIZABLE, true);
InOrder ordered = inOrder(con);
ordered.verify(con).setCatalog("myCatalog");
ordered.verify(con).setSchema("mySchema");
ordered.verify(con).setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
ordered.verify(con).setReadOnly(true);
ordered.verify(con).setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
ordered.verify(con).setAutoCommit(false);

Loading…
Cancel
Save