声明:以下只是个人的一些理解,并非正确,仅供借鉴参考。
数据库的操作是开发中经常会碰见的一个问题,对于刚刚开始学习JAVA的朋友来说,可能对于数据源、连接池这些概念还不熟悉,本文主要是通过一个简单的示例,帮助大家认识这些东西,当然本文的一些观点并不一定完全正确,仅做参考。下面下介绍下连接池,连接池的目的主要是为了解决重复、频繁地创建数据库连接,解决一些资源与效果方面的问题。建立数据库连接就好比是在一条河上建一座桥,数据的传输就好比是桥建成后,交通工具借助其的使用。由此看来,建立数据库连接的成本是比较高的。建立数据库连接池主要是事先先建立一堆连接放入连接池中,就好比先建好几座桥,然后具体要用数据库连接的时候便可以去连接池中取,就好比要用的时候去选一座桥到河的另一岸。不知道绕来绕去绕了半天大家是否对连接池有了初步的一些认识。而我这里所谓的数据源其实也就是对于这一系列机制及操作的一种封装。
以下是核心代码部分,其实实现写的比较简单,同时对SimpleConnection类也省略了部分代码,需要的朋友可以点击下载工程。这里主要是做一个简单的演示,便于刚学习的朋友能够快速了解。同时,在SimpleConnection类中也使用了代理模式,在JdbcUtils类中使用了单例模式,希望对于大家认识设计模式也有所帮助。大家可以点击下载工程,工程的使用方法是解压,直接导入Myeclipse即可使用,Global类中,是对于一些全局量的定义,方便演示,所以也并没有采取读配置文件的方式实现。也可点击http://sites.google.com/site/gwikimo/ 进行下载。
(1)数据源,主要是实现了连接池的功能,因为在池中对于连接的存取操作比较频繁,所以在此使用了LinkedList实现,相对来说效率 上应该优于ArrayList
package org.wiki.datasource.core;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import org.wiki.datasource.global.Global;
/**
* 数据源核心类,用于对于数据库连接的管理
* @author Wiki.M
* @version 0.1
*/
public class SimpleDataSource {
//初始化数据源连接数
private int initCount = Global.INIT_COUNT;
//数据源最大连接数数
private int maxCount = Global.MAX_COUNT;
//数据源当前存在的链接数
private int currentCount = 0;
//创建连接池对象示例
private LinkedList<Connection> connectionPool = new LinkedList<Connection>();
/**
* 默认构造方法,初始化连接池
*/
public SimpleDataSource(){
try {
initConnction();
} catch (SQLException e) {
e.printStackTrace();
//初始化失败
throw new ExceptionInInitializerError(e);
}
}
/**
* 创建数据库链接
* @return 返回Connection类型
* @throws SQLException 数据库异常类
*/
private Connection createConnection() throws SQLException{
return new SimpleConnection(DriverManager.getConnection(Global.URL, Global.USER_NAME, Global.PASSWORD),this);
}
/**
* 初始化连接,根据初始连接数,创建多个连接放入连接池
* 即放入一个LinkedList对象中
* @throws SQLException 数据库异常类
*/
private void initConnction() throws SQLException{
for(int i = 0;i < initCount;i++){
connectionPool.add(createConnection());
currentCount++;
}
}
/**
* 获取数据源连接池中的连接
* @return 返回Connection类型
* @throws SQLException 数据库异常类
* @throws InterruptedException 异常类
*/
public Connection getConnection() throws SQLException, InterruptedException{
//锁定连接池对象,防止多线程操作时产生的错误
synchronized(connectionPool){
//当连接池中还有连接时
if(connectionPool.size() > 0){
return connectionPool.removeFirst();//默认从LinkedList头部取连接对象
}else if(currentCount < maxCount){
//当连接池中连接已用完,但当前连接数仍没超过允许的最大连接数时
return createConnection();
}else {
//除以上两种情况外抛出异常
throw new SQLException("连接已用完。。。");
}
}
}
/**
* 释放连接资源
* @param conn 数据库连接Connection
* @param st Statement对象实例
* @param rs ResultSet对象
*/
public void free(Connection conn,Statement st,ResultSet rs){
free(conn);
try{
if(null != st) st.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
try{
if(null != rs) rs.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
/**
* 释放连接,即将当前连接放回连接池中
* @param conn Connection对象实例
*/
public void free(Connection conn){
connectionPool.addLast(conn);//默认放入LinkedList尾部
}
}
(2)自定义Connection实现,写这个类的用途已在类说明中注明
package org.wiki.datasource.core;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
/**
* 自定义Connection的实现,
* 主要为解决利用Connection的close()方法释放连接时将当前连接放回连接池而非关闭连接
* 基于代理模式实现,持有realConnection真实连接与dataSource数据源对象,实现了对
* 真实连接的代理
* @author Wiki.M
* @version 0.1
*/
public class SimpleConnection implements Connection{
//真实连接对象
private Connection realConnection;
//数据源对象
private SimpleDataSource dataSource;
/**
* 有参构造方法
* @param realConnection 真实连接对象实例
* @param dataSource 数据源对象
*/
public SimpleConnection(Connection realConnection,SimpleDataSource dataSource){
this.realConnection = realConnection;
this.dataSource = dataSource;
}
/**
* 实现了对连接对象的释放
*/
public void close() throws SQLException {
System.out.println("SimpleConnection close()....");
dataSource.free(this);
}
}
(3)JDBC数据库操作工具类
package org.wiki.datasource.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.wiki.datasource.core.SimpleDataSource;
import org.wiki.datasource.global.Global;
/***
* JDBC工具类,用于数据库相关操作,采用单例模式实现
* @author Wiki.M
* @version 0.1
*/
public class JdbcUtils {
private static JdbcUtils jdbcUtils = null;//JDBC用户类实例对象
private static SimpleDataSource sds = null;
/**
* 加载数据库驱动,初始化连接数据库的相关属性。
*/
static {
try {
//加载数据库驱动
Class.forName(Global.DATABASE_DRIVER);
//创建数据源
sds = new SimpleDataSource();
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new ExceptionInInitializerError(e);
}
}
/**
* 私有构造方法,
* 防止new JdbcUtils()方式创建对象
*/
private JdbcUtils() {
}
/**
* 获取JdbcUtils对象示例,单例
* @return 返回JdbcUtils对象实例
*/
public static JdbcUtils getInstance() {
if (jdbcUtils == null) {
//锁定当前对象,防止多线程操作时创建多个对象
synchronized (JdbcUtils.class) {
if (jdbcUtils == null) {
jdbcUtils = new JdbcUtils();
return jdbcUtils;
}
}
}
return jdbcUtils;
}
/**
* 创建数据库连接
* @return 返回Connection对象实例
* @throws InterruptedException
* @throws SQLException
*/
public static Connection getConnection() throws SQLException, InterruptedException {
return sds.getConnection();
}
/**
* 释放数据库操作资源
* @param conn
* @param st
* @param rs
*/
public static void free(Connection conn, Statement st, ResultSet rs) {
sds.free(conn,st,rs);
}
}