Fix #177 implement full transaction state tracking

pull/180/head
Brett Wooldridge 10 years ago
parent 28662ee045
commit 22389819d5

@ -20,6 +20,7 @@ import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Wrapper;
import java.util.HashSet;
@ -51,6 +52,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
private FastList<Statement> openStatements;
private boolean forceClose;
private boolean commitStateDirty;
private boolean isAnythingDirty;
private boolean isAutoCommitDirty;
private boolean isCatalogDirty;
@ -92,7 +94,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
/** {@inheritDoc} */
@Override
public PoolBagEntry getPoolBagEntry()
public final PoolBagEntry getPoolBagEntry()
{
return bagEntry;
}
@ -127,6 +129,13 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
}
}
/** {@inheritDoc} */
@Override
public final void markCommitStateDirty()
{
commitStateDirty = true;
}
// ***********************************************************************
// Internal methods
// ***********************************************************************
@ -138,7 +147,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
}
}
private <T extends Statement> T trackStatement(T statement)
private final <T extends Statement> T trackStatement(T statement)
{
openStatements.add(statement);
@ -190,7 +199,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
}
try {
if (!delegate.getAutoCommit()) {
if (commitStateDirty && !delegate.getAutoCommit()) {
delegate.rollback();
}
@ -218,170 +227,122 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
/** {@inheritDoc} */
@Override
public final Statement createStatement() throws SQLException
public Statement createStatement() throws SQLException
{
checkClosed();
try {
Statement proxyStatement = ProxyFactory.getProxyStatement(this, delegate.createStatement());
return trackStatement(proxyStatement);
}
catch (SQLException e) {
throw checkException(e);
}
Statement proxyStatement = ProxyFactory.getProxyStatement(this, delegate.createStatement());
return trackStatement(proxyStatement);
}
/** {@inheritDoc} */
@Override
public final Statement createStatement(int resultSetType, int concurrency) throws SQLException
public Statement createStatement(int resultSetType, int concurrency) throws SQLException
{
checkClosed();
try {
Statement proxyStatement = ProxyFactory.getProxyStatement(this, delegate.createStatement(resultSetType, concurrency));
return trackStatement(proxyStatement);
}
catch (SQLException e) {
throw checkException(e);
}
Statement proxyStatement = ProxyFactory.getProxyStatement(this, delegate.createStatement(resultSetType, concurrency));
return trackStatement(proxyStatement);
}
/** {@inheritDoc} */
@Override
public final Statement createStatement(int resultSetType, int concurrency, int holdability) throws SQLException
public Statement createStatement(int resultSetType, int concurrency, int holdability) throws SQLException
{
checkClosed();
try {
Statement proxyStatement = ProxyFactory.getProxyStatement(this, delegate.createStatement(resultSetType, concurrency, holdability));
return trackStatement(proxyStatement);
}
catch (SQLException e) {
throw checkException(e);
}
Statement proxyStatement = ProxyFactory.getProxyStatement(this, delegate.createStatement(resultSetType, concurrency, holdability));
return trackStatement(proxyStatement);
}
/** {@inheritDoc} */
@Override
public final CallableStatement prepareCall(String sql) throws SQLException
public CallableStatement prepareCall(String sql) throws SQLException
{
checkClosed();
try {
CallableStatement pcs = ProxyFactory.getProxyCallableStatement(this, delegate.prepareCall(sql));
return trackStatement(pcs);
}
catch (SQLException e) {
throw checkException(e);
}
CallableStatement pcs = ProxyFactory.getProxyCallableStatement(this, delegate.prepareCall(sql));
return trackStatement(pcs);
}
/** {@inheritDoc} */
@Override
public final CallableStatement prepareCall(String sql, int resultSetType, int concurrency) throws SQLException
public CallableStatement prepareCall(String sql, int resultSetType, int concurrency) throws SQLException
{
checkClosed();
try {
CallableStatement pcs = ProxyFactory.getProxyCallableStatement(this, delegate.prepareCall(sql, resultSetType, concurrency));
return trackStatement(pcs);
}
catch (SQLException e) {
throw checkException(e);
}
CallableStatement pcs = ProxyFactory.getProxyCallableStatement(this, delegate.prepareCall(sql, resultSetType, concurrency));
return trackStatement(pcs);
}
/** {@inheritDoc} */
@Override
public final CallableStatement prepareCall(String sql, int resultSetType, int concurrency, int holdability) throws SQLException
public CallableStatement prepareCall(String sql, int resultSetType, int concurrency, int holdability) throws SQLException
{
checkClosed();
try {
CallableStatement pcs = ProxyFactory.getProxyCallableStatement(this, delegate.prepareCall(sql, resultSetType, concurrency, holdability));
return trackStatement(pcs);
}
catch (SQLException e) {
throw checkException(e);
}
CallableStatement pcs = ProxyFactory.getProxyCallableStatement(this, delegate.prepareCall(sql, resultSetType, concurrency, holdability));
return trackStatement(pcs);
}
/** {@inheritDoc} */
@Override
public final PreparedStatement prepareStatement(String sql) throws SQLException
public PreparedStatement prepareStatement(String sql) throws SQLException
{
checkClosed();
try {
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql));
return trackStatement(proxyPreparedStatement);
}
catch (SQLException e) {
throw checkException(e);
}
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql));
return trackStatement(proxyPreparedStatement);
}
/** {@inheritDoc} */
@Override
public final PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
{
checkClosed();
try {
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, autoGeneratedKeys));
return trackStatement(proxyPreparedStatement);
}
catch (SQLException e) {
throw checkException(e);
}
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, autoGeneratedKeys));
return trackStatement(proxyPreparedStatement);
}
/** {@inheritDoc} */
@Override
public final PreparedStatement prepareStatement(String sql, int resultSetType, int concurrency) throws SQLException
public PreparedStatement prepareStatement(String sql, int resultSetType, int concurrency) throws SQLException
{
checkClosed();
try {
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, resultSetType, concurrency));
return trackStatement(proxyPreparedStatement);
}
catch (SQLException e) {
throw checkException(e);
}
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, resultSetType, concurrency));
return trackStatement(proxyPreparedStatement);
}
/** {@inheritDoc} */
@Override
public final PreparedStatement prepareStatement(String sql, int resultSetType, int concurrency, int holdability) throws SQLException
public PreparedStatement prepareStatement(String sql, int resultSetType, int concurrency, int holdability) throws SQLException
{
checkClosed();
try {
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, resultSetType, concurrency, holdability));
return trackStatement(proxyPreparedStatement);
}
catch (SQLException e) {
throw checkException(e);
}
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, resultSetType, concurrency, holdability));
return trackStatement(proxyPreparedStatement);
}
/** {@inheritDoc} */
@Override
public final PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
{
checkClosed();
try {
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnIndexes));
return trackStatement(proxyPreparedStatement);
}
catch (SQLException e) {
throw checkException(e);
}
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnIndexes));
return trackStatement(proxyPreparedStatement);
}
/** {@inheritDoc} */
@Override
public final PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
{
checkClosed();
try {
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnNames));
return trackStatement(proxyPreparedStatement);
}
catch (SQLException e) {
throw checkException(e);
}
PreparedStatement proxyPreparedStatement = ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnNames));
return trackStatement(proxyPreparedStatement);
}
/** {@inheritDoc} */
@Override
public void commit() throws SQLException
{
delegate.commit();
commitStateDirty = false;
}
/** {@inheritDoc} */
@Override
public void rollback() throws SQLException
{
delegate.rollback();
commitStateDirty = false;
}
/** {@inheritDoc} */
@Override
public void rollback(Savepoint savepoint) throws SQLException
{
delegate.rollback(savepoint);
commitStateDirty = false;
}
/** {@inheritDoc} */
@ -402,61 +363,38 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
/** {@inheritDoc} */
@Override
public final void setAutoCommit(boolean autoCommit) throws SQLException
public void setAutoCommit(boolean autoCommit) throws SQLException
{
checkClosed();
try {
delegate.setAutoCommit(autoCommit);
isAnythingDirty = true;
isAutoCommitDirty = (autoCommit != parentPool.isAutoCommit);
}
catch (SQLException e) {
throw checkException(e);
}
delegate.setAutoCommit(autoCommit);
isAnythingDirty = true;
isAutoCommitDirty = (autoCommit != parentPool.isAutoCommit);
}
/** {@inheritDoc} */
@Override
public final void setReadOnly(boolean readOnly) throws SQLException
public void setReadOnly(boolean readOnly) throws SQLException
{
checkClosed();
try {
delegate.setReadOnly(readOnly);
isAnythingDirty = true;
isReadOnlyDirty = (readOnly != parentPool.isReadOnly);
}
catch (SQLException e) {
throw checkException(e);
}
delegate.setReadOnly(readOnly);
isAnythingDirty = true;
isReadOnlyDirty = (readOnly != parentPool.isReadOnly);
}
/** {@inheritDoc} */
@Override
public final void setTransactionIsolation(int level) throws SQLException
public void setTransactionIsolation(int level) throws SQLException
{
checkClosed();
try {
delegate.setTransactionIsolation(level);
isAnythingDirty = true;
isTransactionIsolationDirty = (level != parentPool.transactionIsolation);
}
catch (SQLException e) {
throw checkException(e);
}
delegate.setTransactionIsolation(level);
isAnythingDirty = true;
isTransactionIsolationDirty = (level != parentPool.transactionIsolation);
}
/** {@inheritDoc} */
@Override
public final void setCatalog(String catalog) throws SQLException
public void setCatalog(String catalog) throws SQLException
{
checkClosed();
try {
delegate.setCatalog(catalog);
isAnythingDirty = true;
isCatalogDirty = (catalog != null && !catalog.equals(parentPool.catalog)) || (catalog == null && parentPool.catalog != null);
}
catch (SQLException e) {
throw checkException(e);
}
delegate.setCatalog(catalog);
isAnythingDirty = true;
isCatalogDirty = (catalog != null && !catalog.equals(parentPool.catalog)) || (catalog == null && parentPool.catalog != null);
}
/** {@inheritDoc} */

@ -53,4 +53,9 @@ public interface IHikariConnectionProxy extends Connection
* @param statement the Statement to remove from tracking
*/
void untrackStatement(Statement statement);
/**
* Sets the commit state of the connection to dirty.
*/
void markCommitStateDirty();
}

@ -19,6 +19,7 @@ package com.zaxxer.hikari.proxy;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Set;
@ -83,6 +84,7 @@ public final class JavassistProxyFactory
// Cast is not needed for these
methodBody = "{ try { return delegate.method($$); } catch (SQLException e) { throw checkException(e); } }";
generateProxyClass(Statement.class, StatementProxy.class, methodBody);
generateProxyClass(ResultSet.class, ResultSetProxy.class, methodBody);
// For these we have to cast the delegate
methodBody = "{ try { return ((cast) delegate).method($$); } catch (SQLException e) { throw checkException(e); } }";
@ -108,6 +110,9 @@ public final class JavassistProxyFactory
else if ("getProxyCallableStatement".equals(methodName)) {
method.setBody("{return new " + packageName + ".CallableStatementJavassistProxy($$);}");
}
else if ("getProxyResultSet".equals(methodName)) {
method.setBody("{return new " + packageName + ".ResultSetJavassistProxy($$);}");
}
}
proxyCt.toClass(classPool.getClassLoader(), getClass().getProtectionDomain());
@ -128,13 +133,11 @@ public final class JavassistProxyFactory
// Make a set of method signatures we inherit implementation for, so we don't generate delegates for these
Set<String> superSigs = new HashSet<String>();
for (CtMethod method : superClassCt.getMethods()) {
if ((method.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT) {
if ((method.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
superSigs.add(method.getName() + method.getSignature());
}
}
methodBody = methodBody.replace("cast", primaryInterface.getName());
Set<String> methods = new HashSet<String>();
Set<Class<?>> interfaces = ClassLoaderUtils.getAllInterfaces(primaryInterface);
for (Class<?> intf : interfaces) {
@ -159,10 +162,21 @@ public final class JavassistProxyFactory
// Clone the method we want to inject into
CtMethod method = CtNewMethod.copy(intfMethod, targetCt, null);
String modifiedBody = methodBody;
// If the super-Proxy has concrete methods (non-abstract), transform the call into a simple super.method() call
CtMethod superMethod = superClassCt.getMethod(intfMethod.getName(), intfMethod.getSignature());
if ((superMethod.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT) {
modifiedBody = modifiedBody.replace("((cast) ", "");
modifiedBody = modifiedBody.replace("delegate", "super");
modifiedBody = modifiedBody.replace("super)", "super");
}
modifiedBody = modifiedBody.replace("cast", primaryInterface.getName());
// Generate a method that simply invokes the same method on the delegate
String modifiedBody;
if (isThrowsSqlException(intfMethod)) {
modifiedBody = methodBody.replace("method", method.getName());
modifiedBody = modifiedBody.replace("method", method.getName());
}
else {
modifiedBody = "{ return ((cast) delegate).method($$); }".replace("method", method.getName()).replace("cast", primaryInterface.getName());

@ -17,6 +17,8 @@
package com.zaxxer.hikari.proxy;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* This is the proxy class for java.sql.PreparedStatement.
@ -34,4 +36,36 @@ public abstract class PreparedStatementProxy extends StatementProxy implements P
// Overridden java.sql.PreparedStatement Methods
// **********************************************************************
/** {@inheritDoc} */
@Override
public boolean execute() throws SQLException
{
connection.markCommitStateDirty();
return ((PreparedStatement) delegate).execute();
}
/** {@inheritDoc} */
@Override
public ResultSet executeQuery() throws SQLException
{
connection.markCommitStateDirty();
ResultSet resultSet = ((PreparedStatement) delegate).executeQuery();
return ProxyFactory.getProxyResultSet(connection, resultSet);
}
/** {@inheritDoc} */
@Override
public int executeUpdate() throws SQLException
{
connection.markCommitStateDirty();
return ((PreparedStatement) delegate).executeUpdate();
}
/** {@inheritDoc} */
@Override
public long executeLargeUpdate() throws SQLException
{
connection.markCommitStateDirty();
return ((PreparedStatement) delegate).executeLargeUpdate();
}
}

@ -19,6 +19,7 @@ package com.zaxxer.hikari.proxy;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import com.zaxxer.hikari.pool.HikariPool;
@ -69,4 +70,10 @@ public final class ProxyFactory
// Body is injected by JavassistProxyFactory
return null;
}
static ResultSet getProxyResultSet(final ConnectionProxy connection, final ResultSet resultSet)
{
// Body is injected by JavassistProxyFactory
return null;
}
}

@ -0,0 +1,86 @@
/*
* Copyright (C) 2013, 2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.proxy;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Wrapper;
/**
* This is the proxy class for java.sql.ResultSet.
*
* @author Brett Wooldridge
*/
public abstract class ResultSetProxy implements ResultSet
{
protected final ConnectionProxy connection;
protected final ResultSet delegate;
protected ResultSetProxy(ConnectionProxy connection, ResultSet resultSet)
{
this.connection = connection;
this.delegate = resultSet;
}
protected final SQLException checkException(SQLException e)
{
return connection.checkException(e);
}
// **********************************************************************
// Overridden java.sql.ResultSet Methods
// **********************************************************************
/** {@inheritDoc} */
@Override
public void updateRow() throws SQLException
{
connection.markCommitStateDirty();
delegate.updateRow();
}
/** {@inheritDoc} */
@Override
public void insertRow() throws SQLException
{
connection.markCommitStateDirty();
delegate.insertRow();
}
/** {@inheritDoc} */
@Override
public void deleteRow() throws SQLException
{
connection.markCommitStateDirty();
delegate.deleteRow();
}
/** {@inheritDoc} */
@Override
@SuppressWarnings("unchecked")
public final <T> T unwrap(Class<T> iface) throws SQLException
{
if (iface.isInstance(delegate)) {
return (T) delegate;
}
else if (delegate instanceof Wrapper) {
return (T) delegate.unwrap(iface);
}
throw new SQLException("Wrapped ResultSet is not an instance of " + iface);
}
}

@ -17,6 +17,7 @@
package com.zaxxer.hikari.proxy;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Wrapper;
@ -28,12 +29,12 @@ import java.sql.Wrapper;
*/
public abstract class StatementProxy implements Statement
{
protected final IHikariConnectionProxy connection;
protected final ConnectionProxy connection;
protected final Statement delegate;
private boolean isClosed;
protected StatementProxy(IHikariConnectionProxy connection, Statement statement)
protected StatementProxy(ConnectionProxy connection, Statement statement)
{
this.connection = connection;
this.delegate = statement;
@ -69,11 +70,133 @@ public abstract class StatementProxy implements Statement
/** {@inheritDoc} */
@Override
public final Connection getConnection() throws SQLException
public Connection getConnection() throws SQLException
{
return connection;
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql) throws SQLException
{
connection.markCommitStateDirty();
return delegate.execute(sql);
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
connection.markCommitStateDirty();
return delegate.execute(sql, autoGeneratedKeys);
}
/** {@inheritDoc} */
@Override
public ResultSet executeQuery(String sql) throws SQLException
{
connection.markCommitStateDirty();
ResultSet resultSet = delegate.executeQuery(sql);
return ProxyFactory.getProxyResultSet(connection, resultSet);
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeUpdate(sql);
}
/** {@inheritDoc} */
@Override
public int[] executeBatch() throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeBatch();
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeUpdate(sql, autoGeneratedKeys);
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeUpdate(sql, columnIndexes);
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeUpdate(sql, columnNames);
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException
{
connection.markCommitStateDirty();
return delegate.execute(sql, columnIndexes);
}
/** {@inheritDoc} */
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException
{
connection.markCommitStateDirty();
return delegate.execute(sql, columnNames);
}
/** {@inheritDoc} */
@Override
public long[] executeLargeBatch() throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeLargeBatch();
}
/** {@inheritDoc} */
@Override
public long executeLargeUpdate(String sql) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql);
}
/** {@inheritDoc} */
@Override
public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql, autoGeneratedKeys);
}
/** {@inheritDoc} */
@Override
public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql, columnIndexes);
}
/** {@inheritDoc} */
@Override
public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException
{
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql, columnNames);
}
/** {@inheritDoc} */
@Override
@SuppressWarnings("unchecked")
public final <T> T unwrap(Class<T> iface) throws SQLException

@ -244,6 +244,9 @@ public final class PoolUtilities
catch (AbstractMethodError e) {
IS_JDBC40 = false;
}
catch (NoSuchMethodError e) {
IS_JDBC40 = false;
}
}
return IS_JDBC40;
@ -265,10 +268,13 @@ public final class PoolUtilities
connection.getNetworkTimeout(); // This will throw AbstractMethodError or SQLException in the case of a non-JDBC 41 compliant driver
IS_JDBC41 = true;
}
catch (SQLFeatureNotSupportedException e) {
IS_JDBC41 = false;
}
catch (AbstractMethodError e) {
IS_JDBC41 = false;
}
catch (SQLFeatureNotSupportedException e) {
catch (NoSuchMethodError e) {
IS_JDBC41 = false;
}
}
@ -289,10 +295,13 @@ public final class PoolUtilities
try {
statement.setQueryTimeout(timeoutSec);
}
catch (SQLFeatureNotSupportedException e) {
queryTimeoutSupported = false;
}
catch (AbstractMethodError e) {
queryTimeoutSupported = false;
}
catch (SQLFeatureNotSupportedException e) {
catch (NoSuchMethodError e) {
queryTimeoutSupported = false;
}
}

@ -131,7 +131,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
/** {@inheritDoc} */
@Override
public final void setCommitStateDirty()
public final void markCommitStateDirty()
{
commitStateDirty = true;
}

@ -57,5 +57,5 @@ public interface IHikariConnectionProxy extends Connection
/**
* Sets the commit state of the connection to dirty.
*/
void setCommitStateDirty();
void markCommitStateDirty();
}

@ -19,6 +19,7 @@ package com.zaxxer.hikari.proxy;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Set;
@ -83,6 +84,7 @@ public final class JavassistProxyFactory
// Cast is not needed for these
methodBody = "{ try { return delegate.method($$); } catch (SQLException e) { throw checkException(e); } }";
generateProxyClass(Statement.class, StatementProxy.class, methodBody);
generateProxyClass(ResultSet.class, ResultSetProxy.class, methodBody);
// For these we have to cast the delegate
methodBody = "{ try { return ((cast) delegate).method($$); } catch (SQLException e) { throw checkException(e); } }";
@ -108,6 +110,9 @@ public final class JavassistProxyFactory
case "getProxyCallableStatement":
method.setBody("{return new " + packageName + ".CallableStatementJavassistProxy($$);}");
break;
case "getProxyResultSet":
method.setBody("{return new " + packageName + ".ResultSetJavassistProxy($$);}");
break;
}
}
@ -160,6 +165,7 @@ public final class JavassistProxyFactory
String modifiedBody = methodBody;
// If the super-Proxy has concrete methods (non-abstract), transform the call into a simple super.method() call
CtMethod superMethod = superClassCt.getMethod(intfMethod.getName(), intfMethod.getSignature());
if ((superMethod.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT) {
modifiedBody = modifiedBody.replace("((cast) ", "");

@ -40,7 +40,7 @@ public abstract class PreparedStatementProxy extends StatementProxy implements P
@Override
public boolean execute() throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return ((PreparedStatement) delegate).execute();
}
@ -48,15 +48,16 @@ public abstract class PreparedStatementProxy extends StatementProxy implements P
@Override
public ResultSet executeQuery() throws SQLException
{
connection.setCommitStateDirty();
return ((PreparedStatement) delegate).executeQuery();
connection.markCommitStateDirty();
ResultSet resultSet = ((PreparedStatement) delegate).executeQuery();
return ProxyFactory.getProxyResultSet(connection, resultSet);
}
/** {@inheritDoc} */
@Override
public int executeUpdate() throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return ((PreparedStatement) delegate).executeUpdate();
}
@ -64,7 +65,7 @@ public abstract class PreparedStatementProxy extends StatementProxy implements P
@Override
public long executeLargeUpdate() throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return ((PreparedStatement) delegate).executeLargeUpdate();
}
}

@ -19,6 +19,7 @@ package com.zaxxer.hikari.proxy;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import com.zaxxer.hikari.pool.HikariPool;
@ -69,4 +70,10 @@ public final class ProxyFactory
// Body is injected by JavassistProxyFactory
return null;
}
static ResultSet getProxyResultSet(final ConnectionProxy connection, final ResultSet resultSet)
{
// Body is injected by JavassistProxyFactory
return null;
}
}

@ -0,0 +1,86 @@
/*
* Copyright (C) 2013, 2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.proxy;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Wrapper;
/**
* This is the proxy class for java.sql.ResultSet.
*
* @author Brett Wooldridge
*/
public abstract class ResultSetProxy implements ResultSet
{
protected final ConnectionProxy connection;
protected final ResultSet delegate;
protected ResultSetProxy(ConnectionProxy connection, ResultSet resultSet)
{
this.connection = connection;
this.delegate = resultSet;
}
protected final SQLException checkException(SQLException e)
{
return connection.checkException(e);
}
// **********************************************************************
// Overridden java.sql.ResultSet Methods
// **********************************************************************
/** {@inheritDoc} */
@Override
public void updateRow() throws SQLException
{
connection.markCommitStateDirty();
delegate.updateRow();
}
/** {@inheritDoc} */
@Override
public void insertRow() throws SQLException
{
connection.markCommitStateDirty();
delegate.insertRow();
}
/** {@inheritDoc} */
@Override
public void deleteRow() throws SQLException
{
connection.markCommitStateDirty();
delegate.deleteRow();
}
/** {@inheritDoc} */
@Override
@SuppressWarnings("unchecked")
public final <T> T unwrap(Class<T> iface) throws SQLException
{
if (iface.isInstance(delegate)) {
return (T) delegate;
}
else if (delegate instanceof Wrapper) {
return (T) delegate.unwrap(iface);
}
throw new SQLException("Wrapped ResultSet is not an instance of " + iface);
}
}

@ -29,12 +29,12 @@ import java.sql.Wrapper;
*/
public abstract class StatementProxy implements Statement
{
protected final IHikariConnectionProxy connection;
protected final ConnectionProxy connection;
protected final Statement delegate;
private boolean isClosed;
protected StatementProxy(IHikariConnectionProxy connection, Statement statement)
protected StatementProxy(ConnectionProxy connection, Statement statement)
{
this.connection = connection;
this.delegate = statement;
@ -79,7 +79,7 @@ public abstract class StatementProxy implements Statement
@Override
public boolean execute(String sql) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.execute(sql);
}
@ -87,7 +87,7 @@ public abstract class StatementProxy implements Statement
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.execute(sql, autoGeneratedKeys);
}
@ -95,15 +95,16 @@ public abstract class StatementProxy implements Statement
@Override
public ResultSet executeQuery(String sql) throws SQLException
{
connection.setCommitStateDirty();
return delegate.executeQuery(sql);
connection.markCommitStateDirty();
ResultSet resultSet = delegate.executeQuery(sql);
return ProxyFactory.getProxyResultSet(connection, resultSet);
}
/** {@inheritDoc} */
@Override
public int executeUpdate(String sql) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeUpdate(sql);
}
@ -111,7 +112,7 @@ public abstract class StatementProxy implements Statement
@Override
public int[] executeBatch() throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeBatch();
}
@ -119,7 +120,7 @@ public abstract class StatementProxy implements Statement
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeUpdate(sql, autoGeneratedKeys);
}
@ -127,7 +128,7 @@ public abstract class StatementProxy implements Statement
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeUpdate(sql, columnIndexes);
}
@ -135,7 +136,7 @@ public abstract class StatementProxy implements Statement
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeUpdate(sql, columnNames);
}
@ -143,7 +144,7 @@ public abstract class StatementProxy implements Statement
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.execute(sql, columnIndexes);
}
@ -151,7 +152,7 @@ public abstract class StatementProxy implements Statement
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.execute(sql, columnNames);
}
@ -159,7 +160,7 @@ public abstract class StatementProxy implements Statement
@Override
public long[] executeLargeBatch() throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeLargeBatch();
}
@ -167,7 +168,7 @@ public abstract class StatementProxy implements Statement
@Override
public long executeLargeUpdate(String sql) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql);
}
@ -175,7 +176,7 @@ public abstract class StatementProxy implements Statement
@Override
public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql, autoGeneratedKeys);
}
@ -183,7 +184,7 @@ public abstract class StatementProxy implements Statement
@Override
public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql, columnIndexes);
}
@ -191,7 +192,7 @@ public abstract class StatementProxy implements Statement
@Override
public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException
{
connection.setCommitStateDirty();
connection.markCommitStateDirty();
return delegate.executeLargeUpdate(sql, columnNames);
}

@ -220,7 +220,7 @@ public final class PoolUtilities
connection.isValid(5); // This will throw AbstractMethodError or SQLException in the case of a non-JDBC 41 compliant driver
IS_JDBC40 = true;
}
catch (AbstractMethodError | SQLFeatureNotSupportedException e) {
catch (NoSuchMethodError | AbstractMethodError | SQLFeatureNotSupportedException e) {
IS_JDBC40 = false;
}
}
@ -244,7 +244,7 @@ public final class PoolUtilities
connection.getNetworkTimeout(); // This will throw AbstractMethodError or SQLException in the case of a non-JDBC 41 compliant driver
IS_JDBC41 = true;
}
catch (AbstractMethodError | SQLFeatureNotSupportedException e) {
catch (NoSuchMethodError | AbstractMethodError | SQLFeatureNotSupportedException e) {
IS_JDBC41 = false;
}
}
@ -265,7 +265,7 @@ public final class PoolUtilities
try {
statement.setQueryTimeout(timeoutSec);
}
catch (AbstractMethodError | SQLFeatureNotSupportedException e) {
catch (NoSuchMethodError | AbstractMethodError | SQLFeatureNotSupportedException e) {
queryTimeoutSupported = false;
}
}

Loading…
Cancel
Save