IDEMPIERE-1235 Add API to support the sharing of non-transactional connection within a single execution thread.

This commit is contained in:
Heng Sin Low 2013-08-02 16:09:45 +08:00
parent 2952930ab4
commit 6cceb11628
4 changed files with 88 additions and 20 deletions

View File

@ -13,13 +13,12 @@
package org.compiere.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.logging.Level;
import org.adempiere.exceptions.DBException;
import org.compiere.util.CStatementVO;
import org.compiere.util.DB;
import org.compiere.util.Trx;
import org.idempiere.db.util.AutoCommitConnectionBroker;
/**
* Dynamic proxy for the CCallableStatement
@ -51,10 +50,7 @@ public class CallableStatementProxy extends PreparedStatementProxy {
}
else
{
if (p_vo.getResultSetConcurrency() == ResultSet.CONCUR_UPDATABLE)
m_conn = DB.getConnectionRW ();
else
m_conn = DB.getConnectionRO();
m_conn = AutoCommitConnectionBroker.getConnection();
conn = m_conn;
}
if (conn == null)

View File

@ -24,6 +24,7 @@ import org.compiere.util.CCachedRowSet;
import org.compiere.util.CStatementVO;
import org.compiere.util.DB;
import org.compiere.util.Trx;
import org.idempiere.db.util.AutoCommitConnectionBroker;
/**
* Dynamic proxy for the CPreparedStatement interface
@ -60,10 +61,7 @@ public class PreparedStatementProxy extends StatementProxy {
if (trx != null) {
conn = trx.getConnection();
} else {
if (p_vo.getResultSetConcurrency() == ResultSet.CONCUR_UPDATABLE)
m_conn = DB.getConnectionRW();
else
m_conn = DB.getConnectionRO();
m_conn = AutoCommitConnectionBroker.getConnection();
conn = m_conn;
}
if (conn == null)

View File

@ -31,6 +31,7 @@ import org.compiere.util.CStatementVO;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Trx;
import org.idempiere.db.util.AutoCommitConnectionBroker;
/**
*
@ -152,10 +153,7 @@ public class StatementProxy implements InvocationHandler {
}
else
{
if (p_vo.getResultSetConcurrency() == ResultSet.CONCUR_UPDATABLE)
m_conn = DB.getConnectionRW ();
else
m_conn = DB.getConnectionRO();
m_conn = AutoCommitConnectionBroker.getConnection();
conn = m_conn;
}
if (conn == null)
@ -183,12 +181,7 @@ public class StatementProxy implements InvocationHandler {
} finally {
if (m_conn != null)
{
try
{
m_conn.close();
}
catch (Exception e)
{}
AutoCommitConnectionBroker.releaseConnection(m_conn);
}
m_conn = null;
p_stmt = null;

View File

@ -0,0 +1,81 @@
/******************************************************************************
* Copyright (C) 2013 Heng Sin Low *
* Copyright (C) 2013 Trek Global *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.idempiere.db.util;
import java.sql.Connection;
import java.sql.SQLException;
import org.compiere.util.DB;
/**
* This class managed the sharing of non-transactional connection per thread.
* @author hengsin
*
*/
public class AutoCommitConnectionBroker {
private static ThreadLocal<ConnectionReference> threadLocalConnection = new ThreadLocal<ConnectionReference>() {
protected ConnectionReference initialValue()
{
return null;
}
};
/**
* Retrieve non-transactional connection for current thread.
* If none have been allocated yet, a new one will be created from the connection pool.
* @return Connection
*/
public static Connection getConnection() {
ConnectionReference connReference = threadLocalConnection.get();
if (connReference != null) {
connReference.referenceCount++;
return connReference.connection;
} else {
Connection connection = DB.createConnection(true, false, Connection.TRANSACTION_READ_COMMITTED);
connReference = new ConnectionReference(connection);
threadLocalConnection.set(connReference);
return connection;
}
}
/**
* Release connection. The connection goes back to pool if reference count is zero.
* @param conn
*/
public static void releaseConnection(Connection conn) {
ConnectionReference connReference = threadLocalConnection.get();
if (connReference != null && connReference.connection == conn) {
connReference.referenceCount--;
if (connReference.referenceCount <= 0) {
threadLocalConnection.set(null);
try {
connReference.connection.close();
} catch (SQLException e) {}
}
} else {
try {
conn.close();
} catch (SQLException e) {}
}
}
private static class ConnectionReference {
protected Connection connection;
protected int referenceCount;
protected ConnectionReference(Connection conn) {
connection = conn;
referenceCount = 1;
}
}
}