📄 connectioninpool.java
字号:
/* * Licensed under the X license (see http://www.x.org/terms.htm) */package org.ofbiz.minerva.pool.jdbc;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.Savepoint;import java.sql.Statement;import java.util.Collection;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Vector;import org.ofbiz.minerva.pool.PoolEvent;import org.ofbiz.minerva.pool.PoolEventListener;import org.ofbiz.minerva.pool.PooledObject;import org.ofbiz.minerva.pool.cache.LeastRecentlyUsedCache;import org.ofbiz.minerva.pool.cache.ObjectCache;/** * Wrapper for database connections in a pool. Handles closing appropriately. * The connection is returned to the pool rather than truly closing, any * outstanding statements are closed, and the connection is rolled back. This * class is also used by statements, etc. to update the last used time for the * connection. * * @author Aaron Mulder (ammulder@alumni.princeton.edu) */public class ConnectionInPool implements PooledObject, ConnectionWrapper { private final static String CLOSED = "Connection has been closed!"; public final static int PS_CACHE_UNLIMITED = 0; public final static int PS_CACHE_DISABLED = -1; public final static HashMap psCaches = new HashMap(); private Connection con; private HashSet statements; private Vector listeners; private int preparedStatementCacheSize = 0; private ObjectCache preparedStatementCache; /** * Creates a new connection wrapper. * @param con The "real" database connection to wrap. */ public ConnectionInPool(Connection con) { this.con = con; preparedStatementCache = (ObjectCache) psCaches.get(con); if (preparedStatementCache == null) { PreparedStatementFactory factory = new PreparedStatementFactory(con); preparedStatementCache = new LeastRecentlyUsedCache(factory, preparedStatementCacheSize); psCaches.put(con, preparedStatementCache); } statements = new HashSet(); listeners = new Vector(); } /** * Creates a new connection wrapper, using the specified maximum size for * the prepared statement cache. * @param con The "real" database connection to wrap. * @param psCacheSize The size of the PreparedStatement cache. * @see #PS_CACHE_UNLIMITED * @see #PS_CACHE_DISABLED */ public ConnectionInPool(Connection con, int psCacheSize) { this.con = con; if (psCacheSize >= 0) { preparedStatementCache = (ObjectCache) psCaches.get(con); if (preparedStatementCache == null) { PreparedStatementFactory factory = new PreparedStatementFactory(con); preparedStatementCache = new LeastRecentlyUsedCache(factory, preparedStatementCacheSize); psCaches.put(con, preparedStatementCache); } } setPSCacheSize(psCacheSize); statements = new HashSet(); listeners = new Vector(); } /** * Sets the number of PreparedStatements to be cached for each * Connection. Your DB product may impose a limit on the number * of open PreparedStatements. * @see #PS_CACHE_UNLIMITED * @see #PS_CACHE_DISABLED */ public void setPSCacheSize(int maxSize) { preparedStatementCacheSize = maxSize; if (maxSize >= 0 && preparedStatementCache != null) preparedStatementCache.setSize(maxSize); } /** * Gets the number of PreparedStatements to be cached for each * Connection. */ public int getPSCacheSize() { return preparedStatementCacheSize; } /** * Adds a listener for pool events. */ public void addPoolEventListener(PoolEventListener listener) { listeners.addElement(listener); } /** * Removes a listener for pool events. */ public void removePoolEventListener(PoolEventListener listener) { listeners.remove(listener); } /** * Gets a reference to the "real" connection. This should only be used if * you need to cast that to a specific type to call a proprietary method - * you will defeat all the pooling if you use the underlying connection * directly. */ public Connection getUnderlyingConnection() { return con; } /** * Closes this connection wrapper permanently. All further calls with throw * a SQLException. */ public void shutdown() { con = null; statements = null; listeners = null; } /** * Updates the last used time for this connection to the current time. */ public void setLastUsed() { firePoolEvent(new PoolEvent(this, PoolEvent.OBJECT_USED)); } /** * Indicates that an error occured on this connection. */ public void setError(SQLException e) { firePoolEvent(new PoolEvent(this, PoolEvent.OBJECT_ERROR)); } /** * Indicates that an error occured on this connection. */ public void setCatastrophicError(SQLException e) { PoolEvent pe = new PoolEvent(this, PoolEvent.OBJECT_ERROR); pe.setCatastrophic(); firePoolEvent(pe); } /** * Indicates that a statement has been closed and no longer needs to be * tracked. Outstanding statements are closed when the connection is * returned to the pool. */ public void statementClosed(Statement st) { statements.remove(st); if ((con != null) && (st instanceof PreparedStatementInPool)) { // Now return the "real" statement to the pool PreparedStatementInPool ps = (PreparedStatementInPool) st; PreparedStatement ups = ps.getUnderlyingPreparedStatement(); if (preparedStatementCacheSize >= 0) { preparedStatementCache.returnObject(ps.getSql(), ups); } else { try { ups.close(); } catch (SQLException e) { } }/* int rsType = ResultSet.TYPE_FORWARD_ONLY; int rsConcur = ResultSet.CONCUR_READ_ONLY; // We may have JDBC 1.0 driver try { rsType = ups.getResultSetType(); rsConcur = ups.getResultSetConcurrency(); } catch (Throwable th) { } PreparedStatementInPool.preparedStatementCache.put( new PSCacheKey(con, ps.getSql(), rsType, rsConcur), ups);*/ } } /** * Prepares a connection to be returned to the pool. All outstanding * statements are closed, and if AutoCommit is off, the connection is * rolled back. No further SQL calls are possible once this is called. */ public void reset() throws SQLException { Collection copy = (Collection) statements.clone(); Iterator it = copy.iterator(); while (it.hasNext()) try { ((Statement) it.next()).close(); } catch (SQLException e) { } if (!con.getAutoCommit()) con.rollback(); con = null; } /** * Dispatches an event to the listeners. */ protected void firePoolEvent(PoolEvent evt) { Vector local = (Vector) listeners.clone(); for (int i = local.size() - 1; i >= 0; i--) if (evt.getType() == PoolEvent.OBJECT_CLOSED) ((PoolEventListener) local.elementAt(i)).objectClosed(evt); else if (evt.getType() == PoolEvent.OBJECT_ERROR) ((PoolEventListener) local.elementAt(i)).objectError(evt); else ((PoolEventListener) local.elementAt(i)).objectUsed(evt); } // ---- Implementation of java.sql.Connection ---- public Statement createStatement() throws SQLException { if (con == null) throw new SQLException(CLOSED); try { StatementInPool st = new StatementInPool(con.createStatement(), this); statements.add(st); return st; } catch (SQLException e) { setError(e); throw e; } } public PreparedStatement prepareStatement(String sql) throws SQLException { return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); } public CallableStatement prepareCall(String sql) throws SQLException { if (con == null) throw new SQLException(CLOSED); try { return con.prepareCall(sql); } catch (SQLException e) { setError(e); throw e; } } public String nativeSQL(String sql) throws SQLException { if (con == null) throw new SQLException(CLOSED); try { return con.nativeSQL(sql); } catch (SQLException e) { setError(e); throw e; } } public void setAutoCommit(boolean autoCommit) throws SQLException { if (con == null) throw new SQLException(CLOSED); try { con.setAutoCommit(autoCommit); } catch (SQLException e) { setError(e); throw e; } } public boolean getAutoCommit() throws SQLException { if (con == null) throw new SQLException(CLOSED); try { return con.getAutoCommit(); } catch (SQLException e) { setError(e); throw e; } } public void commit() throws SQLException { if (con == null) throw new SQLException(CLOSED); try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -