日期:2014-05-16  浏览次数:20483 次

2009-12-02传智播客 数据库——JDBC开发 连接池与事务(转载)
Today is JDBC高级部分,课程的主要内容有连接池与事务。这都是在应用开发中比较常用,比较重要的。

一、使用配置文件优化JDBCUtil,使用工厂模式隔离DAO层:

昨天有说过将对数据库获取连接和释放的操作单封装到一个类中,如:

import java.sql.*;
import cn.itcast.cc.exception.JDBCUtilException;

/**
* JDBC工具类
*
* @author Administrator
*
*/
public class JDBCUtil {
// 连接数据库时所需要的参数
private static String url = "jdbc:mysql://localhost:3306/jdbc";
private static String username = "root";
private static String password = "root";
// 类被加载时就加载驱动
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

// 获取连接
public static Connection getConnection() throws JDBCUtilException {
try {
return DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
throw new JDBCUtilException(e);
}
}

// 释放连接等资源,下面是一种健康的释放方式
public static void release(ResultSet rs, Statement sta, Connection conn)
throws JDBCUtilException {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
throw new JDBCUtilException(e);
}
rs = null;
}

if (sta != null) {
try {
sta.close();
} catch (SQLException e) {
throw new JDBCUtilException(e);
}
sta = null;
}

if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
throw new JDBCUtilException(e);
}
conn = null;
}
}
}
从上面我们看到其中装载数据库驱动和获取数据库连接的代码: Class.forName("com.mysql.jdbc.Driver");

DriverManager.getConnection(url, username, password);



我们使用了固定的url,它是一个成员。在以后的开发中,如果要使用其他的数据库或者数据库的用户名密码被改变了,我们还需要手动的修改上边的代码,重新编译。这是一种不良的设计方法,为了使我们的代码与数据库分离,我们可以将这些参数配置到配置文件中。这样在需要使用时去读取配置文件中的对应值即可。以后换数据库或更改了用户名,直接修改一下配置文件即可。

昨天有提到过DAO层,DAO层专门用于处理对数据库的CURD操作等,比如,添加用户、查找用户、修改用户、删除用户,我们可以把这些操作封装到一个类中(UserDao.java),它所处位置就是DAO层。比如,用于处理用户注册的Servlet,在这个Servlet中直接实例化一个UserDao对象。然后调用userDaoObj.add(userbean);方法即可实现用户的注册。

如果我想换一种数据存储方式,比如配置文件,我只将用户信息保存在配置文件中。这样我就需要修改UserDao.java,但有时又需要UserDao.java这个功能类怎么办?我只能重新创建一个专门处理配置文件数据的类(UserDaoPro.java)。这样我又需要修改Servlet中的代码,将实例化UserDao的代码修改为实例化UserDaoPro对象。那UserDaoPro与UserDao的接口是不是相同的呢?如果不相同麻烦就大了,JAVA是提倡使用接口编程的,就是为了实现接口的统一化。

可见,上面的这种实现方式是存在问题的。即使接口统一,我们还需要修改Servlet中的代码。此时工厂模式派上了用场,还记得工厂模式吧!是这样的:

1.定义一个UserDao接口,统一对用户操作的接口。

2.定义一个UserDaoFactory的工厂类,专门生产UserDao对象。

3. UserDaoFactory工厂从配置文件中读取实现了UserDao接口的类名称。使用此类生产产品——UserDao对象。

4.在Servlet中使用UserDaoFactory工厂来创建需要的UserDao对象。

这样就实现了DAO层与Servlet的完全分离!完美!

二、数据库连接池:

每当有一个新的连接发生时,数据库就需要创建一个Connection对象来处理连接。访问结束后,Connection对象被释放。数据库创建一个Connection对象,是十分耗时且消耗较大的服务器资源。试想,如果有500个用户同时访问数据库,数据库同时创建500个Connection将会是什么样子!因此,连接池这一技术诞生了。

连接池,在服务器加载WEB应用后。WEB应用会自动创建一个连接池,池中包含多个Connection对象。每当有新的连接请求时,便从这个池中拿出一个Connection对象用于处理连接,使用完成后,便还回给这个池子。下面代码为连接池的实现原理:

import java.io.*;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import javax.sql.DataSource;

/**
* 自己编写的简单连接池类,单例模式实现。
*
* @author Administrator
*
*/
public class JDBCUtil implements DataSource {
private static LinkedList<Connection> conns = new LinkedList<Connection>();
private static JDBCUtil myjdbcutil = new JDBCUtil();

private JDBCUtil() {
// 取配置文件
InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream(
"cn/itcast/cc/db/myjdbc.properties");
// 装载配置文件
Properties pro = new Properties();
try {
pro.load(in);
} catch (IOException e) {
e.printStackTrace();