mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
bug fixed for sharedPreparedStatement
This commit is contained in:
@@ -151,19 +151,7 @@ public final class ConnectionHolder {
|
||||
}
|
||||
|
||||
public boolean isPoolPreparedStatements() {
|
||||
// if (dataSource.isOracle()) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
boolean poolPreparedStatements = dataSource.isPoolPreparedStatements();
|
||||
if (poolPreparedStatements) {
|
||||
boolean transaction = !isUnderlyingAutoCommit();
|
||||
if (transaction && !dataSource.isSharePreparedStatements()) {
|
||||
poolPreparedStatements = false;
|
||||
}
|
||||
}
|
||||
|
||||
return poolPreparedStatements;
|
||||
return dataSource.isPoolPreparedStatements();
|
||||
}
|
||||
|
||||
public Connection getConnection() {
|
||||
|
||||
@@ -118,6 +118,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
return;
|
||||
}
|
||||
|
||||
stmt.getPreparedStatementHolder().decrementInUseCount();
|
||||
if (holder.isPoolPreparedStatements()) {
|
||||
holder.getStatementPool().put(stmt.getPreparedStatementHolder());
|
||||
|
||||
@@ -202,7 +203,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
|
||||
|
||||
@@ -210,6 +211,11 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
|
||||
return rtnVal;
|
||||
}
|
||||
|
||||
private void initStatement(PreparedStatementHolder stmtHolder) throws SQLException {
|
||||
stmtHolder.incrementInUseCount();
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
|
||||
@@ -236,7 +242,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
|
||||
|
||||
@@ -271,7 +277,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
|
||||
|
||||
@@ -302,7 +308,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
|
||||
|
||||
@@ -333,7 +339,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
|
||||
|
||||
@@ -364,7 +370,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
|
||||
|
||||
@@ -397,7 +403,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledCallableStatement rtnVal = new DruidPooledCallableStatement(this, stmtHolder);
|
||||
|
||||
@@ -432,7 +438,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledCallableStatement rtnVal = new DruidPooledCallableStatement(this, stmtHolder);
|
||||
|
||||
@@ -465,7 +471,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec
|
||||
}
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmtHolder.getStatement());
|
||||
initStatement(stmtHolder);
|
||||
|
||||
DruidPooledCallableStatement rtnVal = new DruidPooledCallableStatement(this, stmtHolder);
|
||||
holder.addTrace(rtnVal);
|
||||
|
||||
@@ -35,6 +35,8 @@ public final class PreparedStatementHolder {
|
||||
|
||||
private boolean enterOracleImplicitCache = false;
|
||||
|
||||
private int inUseCount = 0;
|
||||
|
||||
public PreparedStatementHolder(PreparedStatementKey key, PreparedStatement stmt){
|
||||
this.key = key;
|
||||
this.statement = stmt;
|
||||
@@ -90,4 +92,19 @@ public final class PreparedStatementHolder {
|
||||
return hitCount;
|
||||
}
|
||||
|
||||
public boolean isInUse() {
|
||||
return inUseCount <= 0;
|
||||
}
|
||||
|
||||
public void incrementInUseCount() {
|
||||
inUseCount++;
|
||||
}
|
||||
|
||||
public void decrementInUseCount() {
|
||||
inUseCount--;
|
||||
}
|
||||
|
||||
public int getInUseCount() {
|
||||
return inUseCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,10 @@ public class PreparedStatementPool {
|
||||
PreparedStatementHolder holder = map.get(key);
|
||||
|
||||
if (holder != null) {
|
||||
holder.incrementHitCount();
|
||||
if (holder.isInUse() && (!dataSource.isSharePreparedStatements())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
dataSource.incrementCachedPreparedStatementHitCount();
|
||||
if (holder.isEnterOracleImplicitCache()) {
|
||||
OracleUtils.exitImplicitCacheToActive(holder.getStatement());
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.alibaba.druid.bvt.pool;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.pool.DruidPooledPreparedStatement;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
public class PSCacheTest extends TestCase {
|
||||
|
||||
private DruidDataSource dataSource;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
dataSource = new DruidDataSource();
|
||||
dataSource.setUrl("jdbc:mock:x1");
|
||||
dataSource.setPoolPreparedStatements(true);
|
||||
dataSource.setMaxOpenPreparedStatements(10);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
JdbcUtils.close(dataSource);
|
||||
}
|
||||
|
||||
public void test_noTxn() throws Exception {
|
||||
Connection conn = dataSource.getConnection();
|
||||
|
||||
String sql = "select 1";
|
||||
|
||||
PreparedStatement stmt0 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;
|
||||
stmt0.close();
|
||||
|
||||
PreparedStatement stmt1 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;
|
||||
|
||||
Assert.assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same
|
||||
|
||||
PreparedStatement stmt2 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;
|
||||
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not same
|
||||
|
||||
stmt1.close();
|
||||
stmt2.close();
|
||||
|
||||
conn.close();
|
||||
}
|
||||
|
||||
public void test_txn() throws Exception {
|
||||
Connection conn = dataSource.getConnection();
|
||||
|
||||
conn.setAutoCommit(false);
|
||||
|
||||
String sql = "select 1";
|
||||
|
||||
PreparedStatement stmt0 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;
|
||||
stmt0.close();
|
||||
|
||||
PreparedStatement stmt1 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;
|
||||
|
||||
Assert.assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same
|
||||
|
||||
PreparedStatement stmt2 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;
|
||||
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not same
|
||||
|
||||
stmt1.close();
|
||||
stmt2.close();
|
||||
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.alibaba.druid.bvt.pool;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.pool.DruidPooledPreparedStatement;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
public class PSCacheTest1 extends TestCase {
|
||||
|
||||
private DruidDataSource dataSource;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
dataSource = new DruidDataSource();
|
||||
dataSource.setUrl("jdbc:mock:x1");
|
||||
dataSource.setPoolPreparedStatements(true);
|
||||
dataSource.setMaxOpenPreparedStatements(10);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
JdbcUtils.close(dataSource);
|
||||
}
|
||||
|
||||
public void test_noTxn() throws Exception {
|
||||
{
|
||||
Connection conn = dataSource.getConnection();
|
||||
|
||||
String sql = "select 1";
|
||||
|
||||
PreparedStatement stmt0 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;
|
||||
stmt0.close();
|
||||
|
||||
PreparedStatement stmt1 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;
|
||||
|
||||
Assert.assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same
|
||||
|
||||
PreparedStatement stmt2 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;
|
||||
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not
|
||||
// same
|
||||
|
||||
conn.close();
|
||||
}
|
||||
{
|
||||
Connection conn = dataSource.getConnection();
|
||||
|
||||
conn.setAutoCommit(false);
|
||||
|
||||
String sql = "select 1";
|
||||
|
||||
PreparedStatement stmt0 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;
|
||||
stmt0.close();
|
||||
|
||||
PreparedStatement stmt1 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;
|
||||
|
||||
Assert.assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same
|
||||
|
||||
PreparedStatement stmt2 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;
|
||||
|
||||
Assert.assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not
|
||||
// same
|
||||
|
||||
stmt1.close();
|
||||
stmt2.close();
|
||||
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.alibaba.druid.bvt.pool;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.pool.DruidPooledPreparedStatement;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
public class PSCacheTest2 extends TestCase {
|
||||
|
||||
private DruidDataSource dataSource;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
dataSource = new DruidDataSource();
|
||||
dataSource.setUrl("jdbc:mock:x1");
|
||||
dataSource.setPoolPreparedStatements(true);
|
||||
dataSource.setMaxOpenPreparedStatements(10);
|
||||
dataSource.setSharePreparedStatements(true);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
JdbcUtils.close(dataSource);
|
||||
}
|
||||
|
||||
public void test_0() throws Exception {
|
||||
Connection conn = dataSource.getConnection();
|
||||
|
||||
String sql = "select 1";
|
||||
|
||||
{
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
PreparedStatement stmt0 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;
|
||||
|
||||
Assert.assertEquals(1, pooledStmt0.getPreparedStatementHolder().getInUseCount());
|
||||
|
||||
PreparedStatement stmt1 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;
|
||||
|
||||
Assert.assertSame(pooledStmt0.getPreparedStatementHolder(), pooledStmt1.getPreparedStatementHolder());
|
||||
|
||||
stmt0.close();
|
||||
stmt1.close();
|
||||
|
||||
conn.close();
|
||||
}
|
||||
|
||||
public void test_txn() throws Exception {
|
||||
Connection conn = dataSource.getConnection();
|
||||
|
||||
conn.setAutoCommit(true);
|
||||
|
||||
String sql = "select 1";
|
||||
|
||||
{
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
PreparedStatement stmt0 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;
|
||||
|
||||
Assert.assertEquals(1, pooledStmt0.getPreparedStatementHolder().getInUseCount());
|
||||
|
||||
PreparedStatement stmt1 = conn.prepareStatement(sql);
|
||||
DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;
|
||||
|
||||
Assert.assertSame(pooledStmt0.getPreparedStatementHolder(), pooledStmt1.getPreparedStatementHolder());
|
||||
|
||||
stmt0.close();
|
||||
stmt1.close();
|
||||
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user