`
xurichusheng
  • 浏览: 335780 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

jdbc 数据库连接池

阅读更多

 

注:有些java类是JDK没有的,请到 http://www.findjar.com/index.x   中查找对应的jar包

 

 

1. 数据库配置文件 (放在工程的 classpath 下)

 

database.properties

 

## oracle ##
#c3p0.driver=oracle.jdbc.driver.OracleDriver
#c3p0.url=jdbc:oracle:thin:@192.168.1.49:1523:DB02

## DB2 ##
c3p0.driver=com.ibm.db2.jcc.DB2Driver
c3p0.url=jdbc:db2://172.20.15.174:50000/test

c3p0.user=admin
c3p0.password=admin
c3p0.initialPoolSize=15
#连接池中保留的最大连接数
c3p0.maxPoolSize=20
#连接池中保留的最小连接数
c3p0.minPoolSize=10
#最大空闲时间,n秒内未使用则连接被丢弃。若为0则永不丢弃
c3p0.maxIdleTime=60
#获得连接的最大等待毫秒数(两次连接中间隔时间)
c3p0.acquireRetryDelay=1000
#当连接池中的连接耗尽的时候c3p0一次同时获取的连接数
c3p0.acquireIncrement=15
#定义在从数据库获取新连接失败后重复尝试的次数
c3p0.acquireRetryAttempts=30
#连接关闭时默认将所有未提交的操作回滚
c3p0.autoCommitOnClose=false
#连接池内单个连接所拥有的最大缓存statements数
c3p0.maxStatementsPerConnection=100
#通过多线程实现多个操作同时被执行
c3p0.numHelperThreads=10


### DPCP ###
#最大等待秒数,单位为毫秒, 超过时间会报出错误信息
dpcp.maxwait=60000

 

2. 配置文件解析类

 

 

import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.apache.log4j.Logger;


/**
 * @ClassName: ParsePropertiesFile
 * @Description: 解析属性文件(*.properties)
 * @author
 * @company
 * @date 2012-11-8
 * @version V1.0
 */

public final class ParsePropertiesFile {

	private static final Logger LOG = Logger
			.getLogger(ParsePropertiesFile.class);

	private static final ParsePropertiesFile instance = new ParsePropertiesFile();

	private ParsePropertiesFile() {
	}

	public static ParsePropertiesFile getInstance() {
		return instance;
	}

	/**
	 * @Title: getConfig
	 * @Description: 解析并读取属性文件(*.properties)
	 * @param propFile
	 *            属性文件路径
	 * @return:Map
	 * @author
	 * @date 2012-11-8
	 */
	public Map<String, String> getConfig(String propFile) {

		InputStream is = null;

		try {
			is = this.getClass().getClassLoader().getResourceAsStream(propFile);

			Properties prop = new Properties();

			prop.load(is);

			Set<Entry<Object, Object>> set = prop.entrySet();
			Iterator<Entry<Object, Object>> it = set.iterator();

			String key = null, value = null;
			Entry<Object, Object> entry = null;

			while (it.hasNext()) {

				entry = it.next();

				key = String.valueOf(entry.getKey()).trim();
				value = String.valueOf(entry.getValue()).trim();

				CommonConstants.propMap.put(key, value);
			}
		} catch (IOException e) {
			LOG.error("parse properties file '"+propFile+"' fail!", e);
		} catch (Exception e) {
			LOG.error("parse properties file '"+propFile+"' fail!", e);
		}
		
		IOUtil.closeStream(is, null);

		return CommonConstants.propMap;
	}
}

 

3. IOUtil

 

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;

import org.apache.log4j.Logger;

public final class IOUtil {

	private static final Logger LOG = Logger.getLogger(IOUtil.class);

	private IOUtil() {
	}

	public static void closeReader(Reader reader) {

		if (null != reader) {
			try {
				reader.close();
				reader = null;
			} catch (IOException e) {
				LOG.error("close reader faile!", e);
			}
		}
	}

	public static void closeStream(InputStream is, OutputStream os) {

		if (null != is) {
			try {
				is.close();
				is = null;
			} catch (IOException e) {
				LOG.error("close InputStream fail!", e);
			}
		}
		
		if (null != os) {
			try {
				os.close();
				os = null;
			} catch (IOException e) {
				LOG.error("close OutputStream fail!", e);
			}
		}
	}
}

 

4. CommonConstants

 

 

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName: CommonConstants
 * @Description: 公共常量类
 * @author wenjianhai
 * @company 广州市道一信息技术有限公司
 * @date 2012-11-8
 * @version V1.0
 */

public final class CommonConstants {

	private CommonConstants() {
	}

	/** 存放属性配置文件(*.properties)中的key-value */
	public static Map<String, String> propMap = new ConcurrentHashMap<String, String>(16);
	
	
}

 

5. 初始化配置文件

 

 

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.log4j.Logger;


/**
 * @ClassName: InitServlet
 * @Description: 服务启动时需要初始化
 * @author 
 * @company 
 * @date 2012-11-8
 * @version V1.0
 */

public class InitServlet extends HttpServlet {

	/**
	 * @Fields serialVersionUID : 序列化id
	 */
	private static final long serialVersionUID = -283273527502774557L;

	private static final Logger log = Logger.getLogger(InitServlet.class);

	@Override
	public void init() throws ServletException {

		log.info("Start to init InitServlet.");

		// 必须要调用父类的初始化方法
		super.init();

		// 解析并读取属性文件
		ParsePropertiesFile.getInstance().getConfig("database.properties");

		log.info("End to init InitServlet.");
	}
	
	
}

 

6. 在 web.xml 中配置servlet

<!-- 初始化 -->
  <servlet>
  	<servlet-name>initServlet</servlet-name>
  	<servlet-class>cn.com.do1.component.init.InitServlet</servlet-class>
  	<load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>initServlet</servlet-name>
  	<url-pattern>/initServlet</url-pattern>
  </servlet-mapping>

 

 

7. 数据库连接池

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Vector;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.time.StopWatch;
import org.apache.log4j.Logger;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * @ClassName: ConnectionPool
 * @Description: 数据库连接池,用于获取第三方数据库的连接
 * @author 
 * @company 
 * @date 2012-11-15
 * @version V1.0
 */

public final class ConnectionPool {

	private Vector<Connection> pool;
	private int poolSize;// 连接池大小

	private static final Logger log = Logger.getLogger(ConnectionPool.class);

	// 线程局部变量
	protected static ThreadLocal<Connection> threadLocalCon = new ThreadLocal<Connection>();

	private static final ConnectionPool instance = new ConnectionPool();

	private static DataSource dataSource;

	/*
	 * 私有构造方法,禁止在外部创建本类的对象,要想获得本类的对象,统一通过getInstance()方法。
	 * 在构造方法中,完成数据池配置文件的加载以及数据池的创建。
	 */
	private ConnectionPool() {
		try {
			this.poolSize = Integer.parseInt(CommonConstants.propMap
					.get("c3p0.maxPoolSize"));

			if (dataSource == null) {
				initDataSource();
			}

			if (null == pool) {
				// 根据配置信息创建连接池
				pool = new Vector<Connection>(poolSize);

				pool = addConnection(poolSize);
			}

		} catch (Exception e) {
			log.error("Init Connection Pool fail!", e);
		}
	}
	/*
	 * 获取本类的对象
	 */
	public static ConnectionPool getInstance() {
		return instance;
	}

	/*
	 * 释放一条连接到连接池中。
	 */
	public synchronized void release(Connection conn) {

		// 重新设置成自动提交(使用事务时,会设置为不自动提交,所以释放连接时,重置成事务自动提交)
		try {
			conn.setAutoCommit(true);
		} catch (SQLException e) {
			log.error("set auto commit fail!", e);
		} catch (Exception e) {
			log.error("set auto commit fail!", e);
		}
		// 重新放入连接池中
		pool.add(conn);

		// 从线程变量中移除
		threadLocalCon.set(null);
	}

	/*
	 * 从连接池中获取一个连接
	 */
	public Connection getConnection() {

		Connection con = threadLocalCon.get();
		try {
			if (con == null || con.isClosed()) {

				while (pool.size() == 0) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						log.error(e);
					}
				}
				synchronized (this) {

					con = pool.get(0);

					threadLocalCon.set(con);
				}
			}
		} catch (Exception e1) {
			log.error("Get Connection fail!", e1);
		}
		return con;
	}

	/*
	 * 根据传入的参数,在连接池中新建num个连接。
	 */
	private Vector<Connection> addConnection(int num) {
		StopWatch sw = new StopWatch();
		sw.start();
		Connection conn = null;
		try {
			// Class.forName(driverClassName);
			for (int i = 0; i < num; i++) {
				// conn = DriverManager.getConnection(url, username, password);
				conn = dataSource.getConnection();
				pool.add(conn);
			}
		} catch (Exception e) {
			log.error("add Connection fail!", e);
		}
		sw.stop();

		log.info("end add connection,the time-consuming is:" + sw.getTime());

		return pool;
	}

	/*
	 * 清空连接池中所有连接。
	 */
	public synchronized void closePool() {
		for (int i = 0; i < pool.size(); i++) {
			try {
				pool.get(i).close();
			} catch (SQLException e) {
				log.error("close Connection Pool fail!", e);
			} catch (Exception e) {
				log.error("close Connection Pool fail!", e);
			}
			pool.remove(i);
		}
	}

	/*
	 * 获取当前连接池中可用连接数
	 */
	public int getAvailableConnectNumber() {
		return pool.size();
	}

	/**
	 * @Title: initDataSource
	 * @Description:初始化数据源,使用 DPCP
	 * @author 
	 * @date 2012-11-16
	 */
	public static void initDataSourceDpcp() {
		// DPCP 连接池
		BasicDataSource ds = new BasicDataSource();

		ds.setDriverClassName(CommonConstants.propMap.get("c3p0.driver"));
		ds.setUrl(CommonConstants.propMap.get("c3p0.url"));
		ds.setUsername(CommonConstants.propMap.get("c3p0.user"));
		ds.setPassword(CommonConstants.propMap.get("c3p0.password"));

		// 设置从数据源中返回的连接是否采用自动提交机制
		ds.setDefaultAutoCommit(Boolean.parseBoolean(CommonConstants.propMap
				.get("c3p0.autoCommitOnClose")));
		// 最大连接数据库连接数,设置为0时,表示没有限制
		ds.setInitialSize(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.initialPoolSize")));
		// 最大连接数
		ds.setMaxActive(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.maxPoolSize")));
		// 在不新建连接的条件下,池中保持空闲的最少连接数
		ds.setMinIdle(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.minPoolSize")));
		// 最大等待秒数,单位为毫秒, 超过时间会报出错误信息
		ds.setMaxWait(Integer.parseInt(CommonConstants.propMap
				.get("dpcp.maxwait")));

		dataSource = ds;
	}

	/**
	 * @Title: initDataSource
	 * @Description:初始化数据源,使用C3P0
	 * @author 
	 * @date 2012-11-16
	 */
	public static void initDataSource() {
		// C3P0 连接池
		ComboPooledDataSource cpds = new ComboPooledDataSource();

		try {
			cpds.setDriverClass(CommonConstants.propMap.get("c3p0.driver"));
		} catch (Exception e) {
			log.error("load driver class fail!", e);
		}
		cpds.setUser(CommonConstants.propMap.get("c3p0.user"));
		cpds.setPassword(CommonConstants.propMap.get("c3p0.password"));
		cpds.setJdbcUrl(CommonConstants.propMap.get("c3p0.url"));

		// 初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 initialPoolSize
		cpds.setInitialPoolSize(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.initialPoolSize")));
		// 连接池中保留的最大连接数。Default: 15 maxPoolSize
		cpds.setMaxPoolSize(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.maxPoolSize")));
		// 连接池中保留的最小连接数。
		cpds.setMinPoolSize(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.minPoolSize")));
		// 获得连接的最大等待毫秒数。Default: 1000 acquireRetryDelay
		cpds.setAcquireRetryDelay(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.acquireRetryDelay")));
		// 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 maxIdleTime
		cpds.setMaxIdleTime(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.maxIdleTime")));

		// 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 acquireIncrement
		cpds.setAcquireIncrement(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.acquireIncrement")));

		// 每60秒检查所有连接池中的空闲连接。Default: 0 idleConnectionTestPeriod
		// cpds.setIdleConnectionTestPeriod(60);

		// 连接关闭时默认将所有未提交的操作回滚。Default: false autoCommitOnClose
		cpds.setAutoCommitOnClose(Boolean.parseBoolean(CommonConstants.propMap
				.get("c3p0.autoCommitOnClose")));

		// maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数
		cpds.setMaxStatementsPerConnection(Integer
				.parseInt(CommonConstants.propMap
						.get("c3p0.maxStatementsPerConnection")));

		// c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成,扩展这些操作可以有效的提升性能 .通过多线程实现多个操作同时被执行
		cpds.setNumHelperThreads(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.numHelperThreads")));

		// 定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 acquireRetryAttempts
		cpds.setAcquireRetryAttempts(Integer.parseInt(CommonConstants.propMap
				.get("c3p0.acquireRetryAttempts")));

		// 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:测试的表必须在初始数据源的时候就存在。Default:
		// null preferredTestQuery
		// cpds.setPreferredTestQuery("select sysdate from dual");

		// 因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
		// 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
		// 等方法来提升连接测试的性能。Default: false testConnectionOnCheckout
		// cpds.setTestConnectionOnCheckout(true);

		// 如果设为true那么在取得连接的同时将校验连接的有效性。Default: false testConnectionOnCheckin
		// cpds.setTestConnectionOnCheckin(true);

		// JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:
		// 0
		// cpds.setMaxStatements(1);

		// 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
		// 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
		// 获取连接失败后该数据源将申明已断开并永久关闭。Default: false breakAfterAcquireFailure
		// cpds.setBreakAfterAcquireFailure(false);

		dataSource = cpds;
	}

	/**
	 * @Title: beginTransaction
	 * @Description: 开始事务
	 * @param conn
	 *            :数据库连接
	 * @author 
	 * @date 2012-11-16
	 */
	public static void beginTransaction(Connection conn) {

		try {
			if (conn != null) {
				if (conn.getAutoCommit()) {
					// 手动提交
					conn.setAutoCommit(false);
				}
			}
		} catch (SQLException e) {
			log.error("set auto commit to false fail!", e);
		} catch (Exception e) {
			log.error("begin Transaction fail!", e);
		}
	}

	/**
	 * @Title: commitTransaction
	 * @Description: 提交事务
	 * @param conn
	 *            :数据库连接
	 * @author 
	 * @date 2012-11-16
	 */
	public static void commitTransaction(Connection conn) {

		try {
			if (conn != null) {
				if (!conn.getAutoCommit()) {
					conn.commit();
				}
			}
		} catch (SQLException e) {
			log.error("commit transaction fail!", e);
		} catch (Exception e) {
			log.error("commit transaction fail!", e);
		}
	}

	/**
	 * @Title: rollbackTransaction
	 * @Description: 事务回滚
	 * @param conn
	 *            :数据库连接
	 * @author 
	 * @date 2012-11-16
	 */
	public static void rollbackTransaction(Connection conn) {

		try {
			if (conn != null) {
				if (!conn.getAutoCommit()) {
					conn.rollback();
				}
			}
		} catch (SQLException e) {
			log.error("rollback transaction fail!", e);
		} catch (Exception e) {
			log.error("rollback transaction fail!", e);
		}
	}

	/**
	 * @Title: resetConnection
	 * @Description: 事务重置
	 * @param conn
	 *            :数据库连接
	 * @author 
	 * @date 2012-11-16
	 */
	public static void resetConnection(Connection conn) {

		try {
			if (conn != null) {
				if (conn.getAutoCommit()) {
					conn.setAutoCommit(false);
				} else {
					conn.setAutoCommit(true);
				}
			}
		} catch (SQLException e) {
			log.error("reset transaction fail!", e);
		} catch (Exception e) {
			log.error("reset transaction fail!", e);
		}
	}

	/**
	 * @Title: setAutoCommit
	 * @Description: 设置是否自动提交事务
	 * @param conn
	 *            数据库连接
	 * @param autoCommit
	 *            :是否自动提交
	 * @author 
	 * @date 2012-11-16
	 */
	public static void setAutoCommit(Connection conn, boolean autoCommit) {

		if (conn != null) {
			try {
				conn.setAutoCommit(autoCommit);
			} catch (SQLException e) {
				log.error("set Auto Commit fail!", e);
			} catch (Exception e) {
				log.error("set Auto Commit fail!", e);
			}
		}
	}
}

 

8. 调用 (DAO层)

/**
	 * @Title: findExpireNotice
	 * @Description: 查找2个月后到期的许可证、工商执照
	 * @param isAll
	 *            0:查找所有已到期的,1:查找2个月后到期的
	 * @return List
	 * @throws Exception
	 * @see cn.com.do1.component.business.licencenotice.dao.ILicencenoticeDAO#findExpireNotice(int)
	 * @author 
	 */
	@Override
	public List<RmLicense> findExpireNotice(YcBusinessMessagePO bm, int isAll)
			throws Exception {

		// 获取中间库连接
		Connection conn = null;
		try {
			conn = ConnectionPool.getInstance().getConnection();
		} catch (Exception e) {
			logger.error("连接中间库失败!", e);
			throw new Exception("连接中间库失败!");
		}

		List<RmLicense> list = new ArrayList<RmLicense>();

		String sql = null;

		if (0 == isAll) {
			// 查找所有已到期的
			sql = "select b.license_code,a.CUST_NAME,a.CORPORATION_NAME,"
					+ "a.MANAGER,a.MANAGER_TEL "
					+ "from rm_cust a,rm_license b where a.cust_id=b.cust_id "
					+ " and status='1' and INVALIDATION_DATE<=current date";
		} else if (1 == isAll) {
			// 查找bm.getWarningLimit()天后到期的
			sql = "select b.license_code,a.CUST_NAME,a.CORPORATION_NAME,"
					+ "a.MANAGER,a.MANAGER_TEL "
					+ "from rm_cust a,rm_license b where a.cust_id=b.cust_id "
					+ " and status='1' "
					+ " and INVALIDATION_DATE=(current date + "
					+ bm.getWarningLimit() + " days)";
		}

		logger.info("查找2个月后到期的许可证、工商执照,the sql is:\r\n" + sql);

		PreparedStatement ps = conn.prepareStatement(sql);

		ResultSet rs = ps.executeQuery();

		RmLicense license = null;

		while (rs.next()) {

			license = new RmLicense();

			license.setLicenseCode(rs.getString("license_code"));
			license.setCustName(rs.getString("CUST_NAME"));
			license.setCorporationName(rs.getString("CORPORATION_NAME"));
			license.setManager(rs.getString("MANAGER"));
			license.setManagerTel(rs.getString("MANAGER_TEL"));

			list.add(license);
		}

		ps.close();
		ConnectionPool.getInstance().release(conn);

		return list;
	}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics