bug fixed for sharedPreparedStatement

This commit is contained in:
温少
2012-05-10 15:47:09 +08:00
parent 6641086507
commit 4dc8a4336f
7 changed files with 283 additions and 23 deletions
@@ -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();
}
}