JDBC与连接池

    JDBC是我们初学JAVA后与数据库打交道用的最初方法,相信都记犹新呵。
    最近找到一套这方面的资料,看完后对JDBC有了更新的认识与了解,下面与大家分享一下小小心得呵。
    我们使用JDBC最原始的一些接口主要是Connection,PreparedStatement,Statement,ResultSet这四大接口,一直只是肤浅的认为将其定义成接口是为了更好的通用及扩展,具体就不知道了。其实我们打开JDK后可以观察到,在java.sql包中大部分都是接口,特别是这些与数据库直接联系的,都是以接口形式出现,那就有疑问了,我们平时明明就是操纵的是这些接口了,但在JDK中没有发现这些接口的具体实现类呢?
    呵,这种设计所包含的智慧不得不让人折服。数据库产品在世面上耳熟能详的就已经有好几种,如SQL SERVER,ORACLE,MYSQL,DB2等,而每种JAVA所支持的数据库都必须实现该套JAVA提供的接口并提供具体操纵该数据库的方法,并且,这些方法在JAVA这套JDBC接口中都已经定义好了,如果你熟悉JAVA设计思想的里氏代换原则,那么话说到此处,你就应该什么都能明白了。
    里氏代换原则:父类能出现的地方,那么子类就一定适合出现!并且,调用的一定是子类的方法。
    再来聊聊连接池。连接池顾名思义就是里面放了好多好多个数据库连接。呵呵,与数据库建立连接其实是非常耗性能的一件事情,但在实际应用中,对于数据库的多连接应用是有一定要求的,一个应用支持容纳的连接越多,应用性能就越快。
    连接池其实就是在一个应用起动的时候一次性加载建立多个连接放入内存中待用,大家都知道从内存中取数据是最有效率的,而且用完后我们调close() 方法其实并不是真正的把该连接资源释放掉,而是又将其连接放回到连接池中备用了。所以这一机制的实行,把高耗都置于程序起动的时候了。随后带来的好处可想而知。
    要说连接池原理嘛,我也不知道,呵呵。不过倒是模拟了一个粗糙得很的假连接池呵,大家见笑了。连接池,可理解一个数据库连接容器不?说到容器,无非就是JAVA类库中的集合类最适合做容器了,小弟不才,使用了LinkedList做为连接容器,因为考虑到回收连接(也就是将用完的连接再插入到该List中)时性能方面,该List肯定比ArrayList快。
    哎,话不多说,看代码吧:
package com.zheng.jdbc.connection;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.zheng.jdbc.conpool.MyConnectionPool;

public final class DateBaseUtils {
private static DateBaseUtils instance = null;
private static MyConnectionPool myConnectionPool = null;
private static final String DRIVER = "oracle.jdbc.driver.OracleDriver";

/**
* 私有构造方法,单例模式
*/
private DateBaseUtils(){}

/**
* 返回该工具类的唯一实例
            * @return
*/
public static DateBaseUtils getInstance(){
if(instance == null) {
synchronized (DateBaseUtils.class) {
if(instance == null){
instance = new DateBaseUtils();
}
}
}
return instance;
}

//静态代码块,保证驱动只会注册一次
static{
try {
Class.forName(DRIVER);
myConnectionPool = new MyConnectionPool();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* 获取一个数据库连接
* @return
*/
public Connection getConnection() throws SQLException{
return myConnectionPool.getConnection();
}

/**
* 释放所有数据库资源
* @param rs 数据库结果集
* @param ps 预编译SQL语句对象
* @param con 数据库连接对象,因为在myConnectionPool对象中模拟了一个数据库连接池机制,
* 所以该处释放指将连接放入到连接池中,而不是真正意义上的释放
*/
public void free(ResultSet rs,Statement ps,Connection con)throws Exception{
try {
rs.close();
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
try {
ps.close();
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
try {
myConnectionPool.free(con);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}

/**
* 重载方法
* @param ps
* @param con
*/
public void free(Statement ps,Connection con) throws Exception{
try {
ps.close();
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
try {
myConnectionPool.free(con);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

/**
* 重载方法,将数据连接放回连接池中
* @param con
*/
public void free(Connection con) throws Exception{
try {
myConnectionPool.free(con);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

/**
*该类为模拟连接池的类
*
*/
package com.zheng.jdbc.conpool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;

/**
* 实现一个简单的连接池机制
*
* @author Administrator zheng2java@sina.com 郑冬华
*
*/
public class MyConnectionPool {

private static final String URL = "jdbc:oracle:thin:@localhost:1521:orcl";
private static final String USERNAME = "scott";
private static final String PASSWORD = "tiger";

private static int initCount = 5;//初始化的连接数
private static int currentCount = 0;//连接创建计数器
private static int maxCount = 10;//最大创建连接数

private static LinkedList<Connection> connectionPool = new LinkedList<Connection>();// 用于存储连接,因为linkedList存储删除快,所以在存储删除频繁的时候用它性能好

/*
* 初始化该类时就在静态块中构造五个数据库连接
*/
static{
try {
for (int i = 0; i < initCount; i++) {
connectionPool.addLast(createConnection());// 将一个连接添加到该linkedList的结尾处,实现后进先出的算法
currentCount++;
}
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}

public MyConnectionPool() {}

/*
* 创建一个连接
* @return 返回一个数据库连接
* @throws Exception
*/
private static Connection createConnection() throws Exception {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);//用Java JDBC数据操作机制中的DriverManager类来创建一个连接
}

/**
* 从模拟连接池中得到一个连接
* @return Connection
*/
public Connection getConnection() throws SQLException{
synchronized (connectionPool) {
if(0 < connectionPool.size()){
return connectionPool.removeFirst();//将连接池(list)中最后一个连接移除并返回,也就是得到一个连接操作
}
if(0 == connectionPool.size() && currentCount < maxCount){//一般连接池都是成几何倍来创建连接的
for(int i = 0 ; i < initCount ; i++){
try {
connectionPool.addLast(createConnection());
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
}else if(0 == connectionPool.size() && currentCount == maxCount){
throw new SQLException("已经超过连接最大数了...");
}
return connectionPool.removeFirst();//将连接池(list)中最后一个连接移除并返回,也就是得到一个连接操作
}
}

/**
* 因为数据库连接池的机制,对于连接的处理不是真正的释放资源,而是将一个连接放回至连接池中,也就是list中。
* @param con 一个数据库连接
*/
public void free(Connection con){
connectionPool.addLast(con);//将用完后传递回来的连接放回至连接中
}
}

以上代码大致能实现一个连接池效用,其实还可以更通用些用动态代理来对其进行更一步优化并支持多数据库的,呵,但本人较懒,实在想睡啦。所以,先goodnight啦

你可能感兴趣的:(oracle,sql,SQL Server,jdbc,db2)