DBConnectionManager.java:连接池管理类
/*
* Created on 2006-3-31
*
* 进行数据库连接池管理
*/
package tea.oracle.pool;
import java.sql.*;
import java.util.*;
import tea.logs.*;
import tea.security.*;
import tea.server.ConfigProperties;
/*******************************************************************************
*
* @author 陈宇翔
*
* TODO To DBConnectionManager实现数据库连接池连接管理,实现线程维护连接池数量。
*/
public class DBConnectionManager {
static private DBConnectionManager instance; // 唯一实例
static private int clients;
protected boolean driverInfoShown;
protected Driver driver;
private String driverString;
private String dbProductName;
private String URL;
private String USER;
private String PASSWD;
private int maxConn;
private int minConn;
private int newConnectionCount;
private String TRANSACTION;
private String AUTOCOMMIT;
protected Vector free;
protected HashMap used;
protected Map connectionKeyMap;
private ConnectManagerPoolThread cmpThread;
/**
* 同步加锁
*
* @param obj
* @return
*/
public synchronized Lock getLock(Object obj) {
Lock lock = (Lock) connectionKeyMap.get(obj);
if (lock == null) {
lock = new Lock();
connectionKeyMap.put(obj, lock);
} else {
lock.count++;
}
return lock;
}
/***************************************************************************
* 同步解锁
*
* @param obj
*/
public synchronized void freeLock(Object obj) {
Lock lock = (Lock) connectionKeyMap.get(obj);
if (lock == null) {
Log4j.debug("Debug: someone is freeing connection without using DBManager.freeLock");
return;
}
lock.count--;
if (lock.count <= 0)
connectionKeyMap.remove(obj);
}
/**
* 返回唯一实例.如果是第一次调用此方法,则创建实例
*
* @return DBConnectionManager 唯一实例
*/
static synchronized public DBConnectionManager getInstance() {
if (instance == null) {
instance = new DBConnectionManager(ConfigProperties
.getOrealcConnectionConfigProperties());
}
clients++;
return instance;
}
/**
* 建构函数私有以防止其它对象创建本类实例
*/
private DBConnectionManager(Properties conProperties) {
Config(conProperties);
driverInfoShown = false;
/*
*/
free = new Vector();
used = new HashMap();
connectionKeyMap = Collections.synchronizedMap(new HashMap());
if (!init()) {
Log4j.error("DBConnectionManager start error!");
} else
Log4j.info("DBConnectionManager start success!!");
}
/***************************************************************************
* 进行数据库连接的配置信息
*
* @param properties
*/
public void Config(Properties properties) {
driverString = properties.getProperty("TEA.DRIVERSTRING").trim();
URL = properties.getProperty("TEA.URL").trim();
USER = properties.getProperty("TEA.USER").trim();
PASSWD = properties.getProperty("TEA.PASSWORD").trim();
maxConn = (new Integer(properties.getProperty("TEA.MAXCONN").trim()))
.intValue();
minConn = (new Integer(properties.getProperty("TEA.MINCONN").trim()))
.intValue();
newConnectionCount = (new Integer(properties.getProperty(
"TEA.NEWCONNECTIONCOUNT").trim())).intValue();
TRANSACTION = properties.getProperty("TEA.TRANSACTION").trim();
AUTOCOMMIT = properties.getProperty("TEA.AUTOCOMMIT").trim();
}
/***************************************************************************
* 创建连接
*
* @param url
* @param user
* @param password
* @return
*/
private Connection createConnection(String url, String user, String password) {
try {
Connection connection;
try {
driver = (Driver) Class.forName(driverString).newInstance();
connection = DriverManager.getConnection(url, user, password);
} catch (Exception exception) {
Log4j.error("Couldn't register JDBC driver: " + driverString);
return null;
}
if (!driverInfoShown)
try {
if (connection != null) {
DatabaseMetaData databasemetadata = connection
.getMetaData();
String s4 = databasemetadata.getDriverName();
if (s4 != null && s4.trim().length() > 0)
Log4j.info("Database Driver Name: " + s4);
String s6 = databasemetadata.getDriverVersion();
if (s6 != null && s6.trim().length() > 0)
Log4j.info("Database Driver Version: " + s6);
driverInfoShown = true;
}
} catch (Exception exception1) {
}
String s3 = TRANSACTION;
if (s3 != null) {
byte byte0 = 8;
if (s3.equalsIgnoreCase("TRANSACTION_NONE"))
byte0 = 0;
else if (s3.equalsIgnoreCase("TRANSACTION_READ_UNCOMMITTED"))
byte0 = 1;
else if (s3.equalsIgnoreCase("TRANSACTION_READ_COMMITTED"))
byte0 = 2;
else if (s3.equalsIgnoreCase("TRANSACTION_REPEATABLE_READ"))
byte0 = 4;
else if (s3.equalsIgnoreCase("TRANSACTION_SERIALIZABLE"))
byte0 = 8;
connection.setTransactionIsolation(byte0);
} else {
connection.setTransactionIsolation(8);
}
if (AUTOCOMMIT == null || AUTOCOMMIT.equalsIgnoreCase("false"))
connection.setAutoCommit(false);
else if (AUTOCOMMIT.equalsIgnoreCase("true"))
connection.setAutoCommit(true);
try {
if (dbProductName == null)
dbProductName = connection.getMetaData()
.getDatabaseProductName();
} catch (Exception exception2) {
Log4j.error("[Couldn't connect to JDBC source:] " + URL);
}
return connection;
} catch (Exception e) {
Log4j.error("[createConnection:] " + e.toString());
return null;
}
}
Connection createUserConnection(String url, String user, String password) {
Connection connection = null;
connection = createConnection(url, user, password);
return connection;
}
/***************************************************************************
* 进行对DBMANAGER初始化
*
* @return
*/
private boolean init() {
String s = "5";// properties.getProperty("mxe.db.retrydbconnection");
for (int i = 0; i < minConn; i++) {
Connection connection = createUserConnection(URL, USER, PASSWD);
if (connection == null) {
if (s != null) {
int j = 0;
try {
j = Integer.parseInt(s);
} catch (Exception exception) {
}
if (j > 0)
try {
Thread thread = Thread.currentThread();
DBRetryThread dbretrythread = new DBRetryThread(j,
thread);
dbretrythread.start();
try {
Thread.sleep((j + 2) * 60 * 1000);
} catch (InterruptedException interruptedexception) {
}
connection = dbretrythread.getRetryConnection();
} catch (Exception exception1) {
}
if (connection != null)
return true;
}
return false;
}
ConRef conref = new ConRef(connection, 0);
free.addElement(conref);
}
cmpThread = new ConnectManagerPoolThread();
cmpThread.start();
return true;
}
public synchronized void destroy() {
int i = 0;
if (cmpThread != null)
cmpThread.finishWork();
try {
this.wait(60010L);
} catch (InterruptedException e) {
Log4j.error("[destroy:] error");
}
for (Enumeration enumeration = free.elements(); enumeration
.hasMoreElements(); i++) {
ConRef conref = (ConRef) enumeration.nextElement();
try {
conref.close();
continue;
} catch (SQLException sqlexception) {
Log4j.error("Error closing db connections for DBManager");
}
}
for (Iterator iterator = used.values().iterator(); iterator.hasNext(); i++) {
ConRef conref1 = (ConRef) iterator.next();
try {
conref1.close();
continue;
} catch (SQLException sqlexception1) {
Log4j.error("Error closing db connections for DBManager");
}
}
used = null;
free = null;
Log4j.info("DBManager finish!");
}
public Connection getConnection(ConnectionKey connectionkey) {
Lock lock = getLock(connectionkey);
Connection connection;
synchronized (lock) {
connection = getConnectionDetail(connectionkey);
}
freeLock(connectionkey);
return connection;
}
public Connection getConnectionDetail(ConnectionKey connectionkey) {
if (connectionkey == null)
return null;
Object objcon = used.get(connectionkey);
if (objcon != null) {
objcon = (ConRef) objcon;
((ConRef) (objcon)).incrementRefCount();
Log4j.debug("getConnection for key: " + connectionkey
+ " Connection = "
+ ((ConRef) (objcon)).getDatabaseConnection() + " count = "
+ ((ConRef) (objcon)).getReferenceCount());
return ((Connection) (objcon));
}
boolean flag = false;
ConRef conref = null;
synchronized (free) {
if (!free.isEmpty()) {
conref = (ConRef) free.elementAt(0);
free.removeElementAt(0);
flag = true;
}
}
if (flag) {
synchronized (used) {
conref.incrementRefCount();
used.put(connectionkey, conref);
}
Log4j.debug("getConnection for key: " + connectionkey
+ " Connection = " + conref.getDatabaseConnection()
+ " count = " + conref.getReferenceCount());
return (Connection) conref;
}
Connection conntmp = null;
conntmp = createUserConnection(URL, USER, PASSWD);
if (conntmp == null)
return null;
ConRef conref1 = new ConRef(conntmp, 1);
used.put(connectionkey, conref1);
return (Connection) conref1;
}
public void freeConnection(ConnectionKey connectionkey) {
Lock lock = getLock(connectionkey);
synchronized (lock) {
freeConnectionDetail(connectionkey);
}
freeLock(connectionkey);
}
public void freeConnectionDetail(ConnectionKey connectionkey) {
Object obj;
if (connectionkey == null)
return;
if (used == null)
return;
synchronized (used) {
obj = used.get(connectionkey);
if (obj != null) {
ConRef conref = (ConRef) obj;
Connection connection = null;
synchronized (used) {
connection = conref.getDatabaseConnection();
conref.decrementRefCount();
if (conref.getReferenceCount() <= 0)
used.remove(connectionkey);
Log4j.debug("freeConnection for key: " + connectionkey
+ " Connection = "
+ conref.getDatabaseConnection() + " count = "
+ conref.getReferenceCount());
if (connection == null)
return;
if (conref.getReferenceCount() <= 0) {
try {
connection.commit();
} catch (SQLException sqlexception) {
try {
connection.close();
} catch (Exception exception2) {
}
Log4j
.debug("freeConnection - discarded lost connection");
return;
}
ConRef conref1 = new ConRef(connection, 0);
synchronized (free) {
free.addElement(conref1);
}
Log4j.debug("freeConnection - Used pool size :"
+ used.size() + " - Free pool size :"
+ free.size());
return;
}
}
}
}
}
/***************************************************************************
* 内部连接池管理类
*
* @author 陈宇翔
*
* TODO To change the template for this generated type comment go to Window -
* Preferences - Java - Code Style - Code Templates
*/
class ConnectManagerPoolThread extends ConnectThread {
private boolean finishWork;
public ConnectManagerPoolThread() {
super("ConnectionPoolThread");
finishWork = false;
}
public void run() {
do {
if (finishWork) {
this.interrupt();
break;
}
DBConnectionManager dbm = DBConnectionManager.getInstance();
if (dbm.free.size() <= minConn) {
int i = 0;
do {
if (i >= newConnectionCount)
break;
java.sql.Connection connection = createUserConnection(
URL, USER, PASSWD);
if (connection == null)
break;
ConRef conref = new ConRef(connection, 0);
dbm.free.addElement(conref);
if (finishWork || dbm.free.size() >= maxConn)
break;
i++;
} while (true);
}
synchronized (dbm.free) {
if (dbm.free.size() > dbm.maxConn) {
for (int j = dbm.free.size() - dbm.maxConn; j > 0;) {
ConRef conref1 = (ConRef) dbm.free.elementAt(0);
dbm.free.removeElementAt(0);
j--;
try {
conref1.close();
} catch (Exception exception) {
}
}
}
}
try {
sleep(60000L);
continue;
} catch (InterruptedException interruptedexception) {
Log4j.error("ConnectionManagerThread error:"
+ interruptedexception);
}
if (this.isMarkedForShutDown() || finishWork)
break;
} while (!this.isMarkedForShutDown());
}
public void finishWork() {
finishWork = true;
}
}
/***************************************************************************
* 内部锁
*
* @author 陈宇翔
*
* TODO To change the template for this generated type comment go to Window -
* Preferences - Java - Code Style - Code Templates
*/
class Lock {
public int count;
public Lock() {
count = 1;
}
}
/***************************************************************************
* 建立连接线程
*
* @author 陈宇翔
*
* TODO To change the template for this generated type comment go to Window -
* Preferences - Java - Code Style - Code Templates
*/
class DBRetryThread extends Thread {
public void run() {
try {
Thread.sleep(60000L);
} catch (Exception exception) {
}
for (; i < count; i++) {
if (i > count) {
orgThread.interrupt();
}
con = createUserConnection(URL, USER, PASSWD);
if (con != null) {
orgThread.interrupt();
}
}
}
public Connection getRetryConnection() {
return con;
}
int count;
Thread orgThread;
Connection con;
int i;
DBRetryThread(int j, Thread thread) {
count = 0;
orgThread = null;
con = null;
i = 0;
count = j;
orgThread = thread;
}
}
}
ConRef.java
/*
* Created on 2006-3-31
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package tea.oracle.pool;
import java.sql.*;
import java.util.Map;
import oracle.jdbc.pool.OracleOCIConnectionPool;
/**
* ConRef
* @author 陈宇翔
* @see 维护数据库连接,提供连接的操作方法和管理方法!
* @version v1.0
*/
public class ConRef implements Connection {
private static final String errorMsg = "Cannot use connection after freeing.";
private int refCount;
private Connection con;
private boolean systemConnection;
private String dbProductName;
private int database;
private static final int DATABASE_ORACLE = 1;
// private static int cursorCount = 0;
String disableServerCursor;
private OracleOCIConnectionPool pool;
public int TRANSACTION_NONE;
public int TRANSACTION_READ_UNCOMMITTED;
public int TRANSACTION_READ_COMMITTED;
public int TRANSACTION_REPEATABLE_READ;
public int TRANSACTION_SERIALIZABLE;
ConRef(Connection connection, int i,
OracleOCIConnectionPool oracleociconnectionpool) {
this(connection, i);
pool = oracleociconnectionpool;
}
ConRef(Connection connection, int i) {
refCount = 0;
con = null;
systemConnection = false;
dbProductName = "";
database = 0;
disableServerCursor = "N";
pool = null;
TRANSACTION_NONE = 0;
TRANSACTION_READ_UNCOMMITTED = 1;
TRANSACTION_READ_COMMITTED = 2;
TRANSACTION_REPEATABLE_READ = 4;
TRANSACTION_SERIALIZABLE = 8;
con = connection;
refCount = i;
try {
dbProductName = connection.getMetaData().getDatabaseProductName();
if (dbProductName.equalsIgnoreCase("oracle"))
database = DATABASE_ORACLE;
} catch (Exception exception1) {
}
}
ConRef(Connection connection) {
this(connection, 0);
systemConnection = true;
}
ConRef(Connection connection,
OracleOCIConnectionPool oracleociconnectionpool) {
this(connection);
pool = oracleociconnectionpool;
}
void incrementRefCount() {
refCount++;
}
void decrementRefCount() {
refCount--;
if (refCount <= 0)
con = null;
}
int getReferenceCount() {
return refCount;
}
Connection getDatabaseConnection() {
return con;
}
public boolean isValid() {
return con != null;
}
private void invalidateConnection(SQLException sqlexception) {
if (systemConnection) {
int i = sqlexception.getErrorCode();
if (database == DATABASE_ORACLE
&& (i == 1012 || i == 1041 || i == 3114 || i == 3113 || i == 17002)
|| database == 2 && i == 0) {
try {
con.close();
} catch (Exception exception) {
}
con = null;
}
}
}
public Statement createStatement() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.createStatement();
}
public PreparedStatement prepareStatement(String s) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareStatement(s);
}
public CallableStatement prepareCall(String s) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareCall(s);
}
public String nativeSQL(String s) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.nativeSQL(s);
}
public void setAutoCommit(boolean flag) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.setAutoCommit(flag);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public boolean getAutoCommit() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.getAutoCommit();
}
public void commit() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.commit();
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public void rollback() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.rollback();
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public void close() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.close();
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public boolean isClosed() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.isClosed();
}
public DatabaseMetaData getMetaData() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.getMetaData();
}
public void setReadOnly(boolean flag) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.setReadOnly(flag);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public boolean isReadOnly() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.isReadOnly();
}
public void setCatalog(String s) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.setCatalog(s);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public String getCatalog() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.getCatalog();
}
public void setTransactionIsolation(int i) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.setTransactionIsolation(i);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public int getTransactionIsolation() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.getTransactionIsolation();
}
public SQLWarning getWarnings() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.getWarnings();
}
public void clearWarnings() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.clearWarnings();
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public Map getTypeMap() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.getTypeMap();
}
public void setTypeMap(Map map) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.setTypeMap(map);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public Statement createStatement(int i, int j) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.createStatement(i, j);
}
public PreparedStatement prepareStatement(String s, int i, int j)
throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareStatement(s, i, j);
}
public CallableStatement prepareCall(String s, int i, int j)
throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareCall(s, i, j);
}
public void setHoldability(int i) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.setHoldability(i);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public int getHoldability() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.getHoldability();
}
public Savepoint setSavepoint() throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.setSavepoint();
}
public Savepoint setSavepoint(String s) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.setSavepoint(s);
}
public void rollback(Savepoint savepoint) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.rollback(savepoint);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
try {
con.releaseSavepoint(savepoint);
} catch (SQLException sqlexception) {
invalidateConnection(sqlexception);
throw sqlexception;
}
}
public Statement createStatement(int i, int j, int k) throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.createStatement(i, j, k);
}
public PreparedStatement prepareStatement(String s, int i, int j, int k)
throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareStatement(s, i, j, k);
}
public CallableStatement prepareCall(String s, int i, int j, int k)
throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareCall(s, i, j, k);
}
public PreparedStatement prepareStatement(String s, int i)
throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareStatement(s, i);
}
public PreparedStatement prepareStatement(String s, int ai[])
throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareStatement(s, ai);
}
public PreparedStatement prepareStatement(String s, String as[])
throws SQLException {
if (con == null)
throw new SQLException(errorMsg);
return con.prepareStatement(s, as);
}
/*
private synchronized int incrementCursorCount() {
cursorCount++;
return cursorCount;
}
*/
public void setConnectionPool(
OracleOCIConnectionPool oracleociconnectionpool) {
pool = oracleociconnectionpool;
}
public OracleOCIConnectionPool getConnectionPool() {
return pool;
}
}
ConnectThreadGroup.java
/*
* Created on 2006-3-31
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package tea.oracle.pool;
/**
* @author Administrator
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class ConnectThreadGroup extends ThreadGroup {
private static Object syncLockObject = new Object();
private static ConnectThreadGroup cnThreadGroup = null;
public ConnectThreadGroup() {
super("Tea Thread Group");
}
public static ConnectThreadGroup getMXThreadGroup() {
synchronized (syncLockObject) {
if (cnThreadGroup == null)
cnThreadGroup = new ConnectThreadGroup();
}
return cnThreadGroup;
}
}
ConnectThread.java
/*
* Created on 2006-3-31
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package tea.oracle.pool;
/**
* @author Administrator
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class ConnectThread extends Thread {
private boolean shutdown;
public ConnectThread(String s) {
super(ConnectThreadGroup.getMXThreadGroup(), "oracle-" + s);
shutdown = false;
}
public void markShutdown() {
shutdown = true;
}
public boolean isMarkedForShutDown() {
return shutdown;
}
}