⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cacheconnection.java

📁 java编写的数据库连接池的源代码。包含有连接池的源码。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
	DBPool - JDBC Connection Pool Manager
	Copyright (c) Giles Winstanley
*/
package snaq.db;

import snaq.util.Reusable;
import java.sql.*;
import java.util.*;

/**
 * Connection wrapper that implements statement caching.
 * Caching is not performed for statements where additional
 * parameters are supplied (ResultSet type/concurrency).
 * @see snaq.db.CachedStatement
 * @see snaq.db.CachedPreparedStatement
 * @see snaq.db.CachedCallableStatement
 * @author Giles Winstanley
 * @todo Ensure changing caching parameters flushes statements if necessary
 */
public final class CacheConnection implements Connection, StatementListener, Reusable
{
	// Constants for determining ResultSet parameters for statements.
	private static int DEFAULT_RESULTSET_TYPE = ResultSet.TYPE_FORWARD_ONLY;
	private static int DEFAULT_RESULTSET_CONCURRENCY = ResultSet.CONCUR_READ_ONLY;
	private static int DEFAULT_RESULTSET_HOLDABILITY = ResultSet.HOLD_CURSORS_OVER_COMMIT;
	
	protected ConnectionPool pool;
	protected Connection con;
	// Statement cache (List of Statement)
	protected List ss = new ArrayList();
	protected List ssUsed = new ArrayList();
	// PreparedStatement cache (Map of List of PreparedStatement)
	protected Map ps = new HashMap();
	protected List psUsed = new ArrayList();
	// CallableStatement cache (Map of List of CallableStatement)
	protected Map cs = new HashMap();
	protected List csUsed = new ArrayList();
	// Non-cached statements
	protected List nonCached = new ArrayList();
	// Other variables
	private boolean cacheS, cacheP, cacheC;
	private int ssReq, ssHit;
	private int psReq, psHit;
	private int csReq, csHit;
	private boolean open = true;


	/**
	 * Creates a new CacheConnection object, using the supplied Connection.
	 */
	public CacheConnection(ConnectionPool pool, Connection con)
	{
		this.pool = pool;
		this.con = con;
		setCacheAll(true);
		ssReq = ssHit = psReq = psHit = csReq = csHit = 0;
	}

	/**
	 * Added to provide caching support.
	 */
	void setOpen()
	{
		open = true;
	}

	/**
	 * Added to provide caching support.
	 */
	boolean isOpen()
	{
		return open;
	}

	/**
	 * Sets whether to use caching for Statements.
	 */
	public void setCacheStatements(boolean cache)
	{
		// Release statements if required
		if (cacheS && !cache)
		{
			try { flushSpareStatements(); }
			catch (SQLException sqle) { pool.log(sqle); }
		}
		this.cacheS = cache;
	}

	/**
	 * Sets whether to use caching for PreparedStatements.
	 */
	public void setCachePreparedStatements(boolean cache)
	{
		// Release statements if required
		if (cacheP && !cache)
		{
			try { flushSparePreparedStatements(); }
			catch (SQLException sqle) { pool.log(sqle); }
		}
		this.cacheP = cache;
	}

	/**
	 * Sets whether to use caching for CallableStatements.
	 */
	public void setCacheCallableStatements(boolean cache)
	{
		// Release statements if required
		if (cacheC && !cache)
		{
			try { flushSpareCallableStatements(); }
			catch (SQLException sqle) { pool.log(sqle); }
		}
		this.cacheC = cache;
	}

	/**
	 * Sets whether to use caching for all types of Statement.
	 */
	public void setCacheAll(boolean cache)
	{
		setCacheStatements(cache);
		setCachePreparedStatements(cache);
		setCacheCallableStatements(cache);
	}

	/** Returns whether caching of CallableStatements is enabled. */
	public boolean isCachingAllStatements() { return cacheS && cacheP && cacheC; }

	/** Returns whether caching of CallableStatements is enabled. */
	public boolean isCachingStatements() { return cacheS; }

	/** Returns whether caching of CallableStatements is enabled. */
	public boolean isCachingPreparedStatements() { return cacheP; }

	/** Returns whether caching of CallableStatements is enabled. */
	public boolean isCachingCallableStatements() { return cacheC; }

	/**
	 * Returns the raw underlying Connection object for which this provides
	 * a wrapper. This is provided as a convenience method for using database-specific
	 * features for which the Connection object needs to be upcast.
	 * (e.g. to use Oracle-specific features needs to be cast to oracle.jdbc.OracleConnection).
	 * <em>To maintain the stability of the pooling system it is important that the
	 * raw connection is not destabilized when used in this way.</em>
	 */
	public Connection getRawConnection()
	{
		return con;
	}

	//******************************
	// Connection interface methods
	//******************************

	/** Overrides method to provide caching support. */
	public Statement createStatement() throws SQLException
	{
		return createStatement(DEFAULT_RESULTSET_TYPE, DEFAULT_RESULTSET_CONCURRENCY, DEFAULT_RESULTSET_HOLDABILITY);
	}

	/** Overrides method to provide caching support. */
	public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
	{
		return createStatement(resultSetType, resultSetConcurrency, DEFAULT_RESULTSET_HOLDABILITY);
	}

	/** Overrides method to provide caching support. */
	public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
	{
		CachedStatement cs = null;
		if (!cacheS)
		{
			cs = new CachedStatement(con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability));
			cs.setStatementListener(this);
		}
		else
		{
			synchronized(ss)
			{
				ssReq++;
				// Find Statement matching criteria required
				for (Iterator it = ss.iterator(); it.hasNext();)
				{
					CachedStatement x = (CachedStatement)it.next();
					if (x.getResultSetType() == resultSetType &&
									x.getResultSetConcurrency() == resultSetConcurrency &&
									x.getResultSetHoldability() == resultSetHoldability)
					{
						cs = x;
						it.remove();
					}
				}
				// Prepare Statement for user
				if (cs != null)
				{
					cs.setOpen();
					ssHit++;
					if (pool.isDebug())
						pool.log("Statement cache hit - " + calcHitRate(ssHit, ssReq));
				}
				else
				{
					cs = new CachedStatement(con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability));
					cs.setStatementListener(this);
					cs.setOpen();
					if (pool.isDebug())
						pool.log("Statement cache miss - " + calcHitRate(ssHit, ssReq));
				}
			}
		}
		ssUsed.add(cs);
		return cs;
	}

	/** Overrides method to provide caching support. */
	public PreparedStatement prepareStatement(String sql) throws SQLException
	{
		return prepareStatement(sql, DEFAULT_RESULTSET_TYPE, DEFAULT_RESULTSET_CONCURRENCY, DEFAULT_RESULTSET_HOLDABILITY);
	}

	/** Overrides method to provide caching support. */
	public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
	{
		return prepareStatement(sql, resultSetType, resultSetConcurrency, DEFAULT_RESULTSET_HOLDABILITY);
	}

	/**
	 * Overrides method to provide caching support.
	 */
	public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
	{
		CachedPreparedStatement cps = null;
		if (!cacheP)
		{
			cps = new CachedPreparedStatement(sql, con.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability));
			cps.setStatementListener(this);
		}
		else
		{
			synchronized(ps)
			{
				psReq++;
				// Get List of cached PreparedStatements with matching SQL
				List list = (List)ps.get(sql);
				if (list != null)
				{
					// Find first free PreparedStatement with matching parameters
					for (Iterator it = list.iterator(); it.hasNext();)
					{
						CachedPreparedStatement x = (CachedPreparedStatement)it.next();
						if (x.getResultSetType() == resultSetType &&
										x.getResultSetConcurrency() == resultSetConcurrency &&
										x.getResultSetHoldability() == resultSetHoldability)
						{
							cps = x;
							it.remove();
						}
					}
				}
				// Prepare PreparedStatement for user
				if (cps != null)
				{
					cps.setOpen();
					psHit++;
					if (pool.isDebug())
						pool.log("PreparedStatement cache hit [" + sql + "," + cps.getParametersString() + "] - " + calcHitRate(psHit, psReq));
				}
				else
				{
					cps = new CachedPreparedStatement(sql, con.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability));
					cps.setStatementListener(this);
					cps.setOpen();
					if (pool.isDebug())
						pool.log("PreparedStatement cache miss [" + sql + "," + cps.getParametersString() + "] - " + calcHitRate(psHit, psReq));
				}
			}
		}
		psUsed.add(cps);
		return cps;
	}

	/** Overrides method to provide caching support. */
	public CallableStatement prepareCall(String sql) throws SQLException
	{
		return prepareCall(sql, DEFAULT_RESULTSET_TYPE, DEFAULT_RESULTSET_CONCURRENCY, DEFAULT_RESULTSET_HOLDABILITY);
	}

	/** Overrides method to provide caching support. */
	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
	{
		return prepareCall(sql, resultSetType, resultSetConcurrency, DEFAULT_RESULTSET_HOLDABILITY);
	}

	/**
	 * Overrides method to provide caching support.
	 */
	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
	{
		CachedCallableStatement ccs = null;
		if (!cacheC)
		{
			ccs = new CachedCallableStatement(sql, con.prepareCall(sql));
			ccs.setStatementListener(this);
		}
		else
		{
			synchronized(cs)
			{
				csReq++;
				// Get List of cached CallableStatements with matching SQL
				List list = (List)cs.get(sql);
				if (list != null)
				{
					// Find first free CallableStatement with matching parameters
					for (Iterator it = list.iterator(); it.hasNext();)
					{
						CachedCallableStatement x = (CachedCallableStatement)it.next();
						if (x.getResultSetType() == resultSetType &&
										x.getResultSetConcurrency() == resultSetConcurrency &&
										x.getResultSetHoldability() == resultSetHoldability)
						{
							ccs = x;
							it.remove();
						}
					}
				}
				// Prepare CallableStatement for user
				if (ccs != null)
				{
					ccs.setOpen();
					csHit++;
					if (pool.isDebug())
						pool.log("CallableStatement cache hit [" + sql + "] - " + calcHitRate(csHit, csReq));
				}
				else
				{
					CallableStatement st = con.prepareCall(sql);
					ccs = new CachedCallableStatement(sql, st);
					ccs.setStatementListener(this);
					ccs.setOpen();
					if (pool.isDebug())
						pool.log("CallableStatement cache miss [" + sql + "] - " + calcHitRate(csHit, csReq));
				}
			}
		}
		csUsed.add(ccs);
		return ccs;
	}
	
	/**
	 * Callback invoked when a statement is closed.
	 */
	public void statementClosed(CachedStatement s) throws SQLException
	{
		if (s instanceof CachedPreparedStatement)
		{
			synchronized(ps)
			{
				String key = ((CachedPreparedStatement)s).getSQLString();
				psUsed.remove(s);
				// If caching disabled close statement
				if (!cacheP)
					s.release();
				else  // else try to recycle it
				{
					try
					{
						s.recycle();
						// Place back in cache
						List list = (List)ps.get(key);
						if (list == null)
						{
							list = new ArrayList();
							ps.put(key, list);
						}
						list.add(s);
					}
					catch (SQLException sqle)
					{
						s.release();
					}
				}
			}
		}
		else if (s instanceof CachedCallableStatement)
		{
			synchronized(cs)
			{
				String key = ((CachedCallableStatement)s).getSQLString();
				csUsed.remove(s);
				// If caching disabled close statement
				if (!cacheC)
					s.release();
				else  // else try to recycle it
				{
					try
					{
						s.recycle();
						// Place back in cache
						List list = (List)cs.get(key);
						if (list == null)
						{
							list = new ArrayList();
							cs.put(key, list);
						}
						list.add(s);
					}
					catch (SQLException sqle)
					{
						s.release();
					}
				}
			}
		}
		else if (s instanceof CachedStatement)
		{
			synchronized(ss)
			{
				ssUsed.remove(s);
				// If caching disabled close statement
				if (!cacheS)
					s.release();
				else  // else try to recycle it
				{
					try
					{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -