自定义JDBC连接池及常用连接池介绍
来源:互联网 发布:easing.js 图片轮播 编辑:程序博客网 时间:2024/06/15 19:37
如果不采用连接池技术, 将导致不断创建和销毁数据库Connection, 造成性能上的损耗. 而数据库连接池技术将在池中创建一定数量的Connection, 当需要Connection时就从池中取出一个, 用完之后归还给连接池, 而不是将其销毁.
自定义数据库连接池的具体步骤分析:
a. 定义MyDataSource类, 实现DataSource接口, 并提供接口中定义的方法. 其中, 核心方法为Connection getConnection().
b. 可以在静态代码块或构造函数中创建多个Connection对象, 并将他们存储在LinkedList中. 当调用MyDataSource对象的getConnection()方法时, 从集合中取出一个Connection返回给调用者. 当调用者使用完Connection并调用Connection对象的close()方法时, 将该Connection对象归还给连接池.
c. 调用Connection对象的close()方法时, 为阻止系统销毁该连接, 而改为将连接归还给连接池, 可以采用包装设计模式. 此时包装的目标类为Connection, 因此需要定义MyConnection类并实现Connection接口. MyConnection类应该存在2个成员: Connection对象和LinkedList<Connection>对象, 这2个成员可以通过构造函数存入. 同时需要覆写close()方法, 在close()方法中实现将Connection添加到集合中.
代码如下:
- public class MyDataSource implements DataSource {
- // 存储Connection对象的集合, 该集合最好采用LinkedList实现, 因为涉及到大量的删除和添加操作.
- private List<Connection> conns = new LinkedList<Connection>();
- public MyDataSource(String propertiesFileName) throws IOException,
- ClassNotFoundException, SQLException {
- // 连接池中Connection对象的数量
- int initialSize = 10;
- // 根据配置文件的名称获得InputStream对象
- InputStream in = MyDataSource.class.getClassLoader()
- .getResourceAsStream(propertiesFileName);
- // 使用Properties读取配置文件
- Properties prop = new Properties();
- prop.load(in);
- String url = prop.getProperty("url");
- String user = prop.getProperty("user");
- String password = prop.getProperty("password");
- String driver = prop.getProperty("driver");
- // 加载数据库驱动
- Class.forName(driver);
- // 根据配置文件中的信息获取数据库连接
- for (int i = 0; i < initialSize; i++) {
- Connection conn = DriverManager.getConnection(url, user, password);
- conns.add(conn);
- }
- }
- @Override
- public Connection getConnection() throws SQLException {
- // 获取从集合中移除的Connection对象, 并将其包装为MyConnection对象后返回.
- Connection conn = conns.remove(0);
- // 测试代码
- System.out.println("获取连接之后, 连接池中的Connection对象的数量为: " + conns.size());
- return new MyConnection(conn, conns);
- }
- private class MyConnection implements Connection {
- private Connection conn;
- private List<Connection> conns;
- public MyConnection(Connection conn, List<Connection> conns) {
- this.conn = conn;
- this.conns = conns;
- }
- // 重写close()方法, 实现调用该方法时将连接归还给连接池
- @Override
- public void close() throws SQLException {
- conns.add(conn);
- // 测试代码
- System.out.println("将连接归还给连接池后, 连接池中的Connection对象的数量为: " + conns.size());
- }
- // 对于其他方法, 直接调用conn对象的相应方法即可
- @Override
- public void clearWarnings() throws SQLException {
- conn.clearWarnings();
- }
- @Override
- public void commit() throws SQLException {
- conn.commit();
- }
- // 省略了其余Connection接口中定义的方法...
- }
- // 省略了其他DataSource接口中定义的方法...
- }
以下是测试代码:
- // create table person(id int primary key auto_increment, name varchar(40), age int);
- public class JDBCPool {
- @Test
- public void myDataSourceTest() {
- Connection conn = null;
- PreparedStatement st = null;
- ResultSet rs = null;
- try {
- MyDataSource pool = new MyDataSource("db.properties");
- conn = pool.getConnection();
- String sql = "insert into person(name, age) values('min', 22)";
- st = conn.prepareStatement(sql);
- st.executeUpdate();
- sql = "select * from person";
- st = conn.prepareStatement(sql);
- rs = st.executeQuery();
- if (rs.next()) {
- System.out.println("id = " + rs.getInt("id") + ", name = "
- + rs.getString("name") + ", age = " + rs.getInt("age"));
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 在release方法内会调用conn对象的close()方法
- release(null, st, conn);
- }
- }
- // 释放资源
- public void release(ResultSet rs, Statement st, Connection conn) {
- try {
- if (rs != null) {
- rs.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- rs = null;
- } finally {
- try {
- if (st != null) {
- st.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- st = null;
- } finally {
- try {
- if (conn != null) {
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- conn = null;
- }
- }
- }
- }
- }
程序的输出为:
获取连接之后, 连接池中的Connection对象的数量为: 9
id = 6, name = min, age = 22
id = 7, name = coolxing, age = 24
将连接归还给连接池后, 连接池中的Connection对象的数量为: 10
可见这个自定义的连接池是可以工作的.
自定义数据库连接池只是为了学习JDBC连接池的原理, 平时项目使用的时候, 还是应该以开源的数据库连接池为主.
常用的数据库连接池为DBCP, C3P0, 以及TOMCAT内置的连接池. 下面简单的介绍以下前两者的使用.
1. DBCP连接池使用步骤:
a. 导入Commons-dbcp.jar和Commons-pool.jar到project中.
b. 获取数据源DataSource对象. 可以直接创建BasicDataSource对象后调用相应的set方法, 如:
DataSource pool = new BasicDataSource();
pool.setUrl("jdbc:mysql://localhost:3306/exercise");
pool.setUsername("root");
pool.setPassword("root");
pool.setDriverClassName("com.mysql.jdbc.Driver");
pool.setInitialSize(10);
也可以通过工厂类加载配置文件获得DataSource对象, 如:
Properties prop = new Properties();
InputStream in = JDBCPool.class.getClassLoader().getResourceAsStream("dbcp.properties");
prop.load(in);
DataSource pool = BasicDataSourceFactory.createDataSource(prop);
c. 调用DataSource对象的getConnection()方法获得连接.
2. C3P0连接池的使用步骤:
a. 导入c3p0-0.9.1.2.jar和c3p0-0.9.1.2-jdk1.3.jar.
b. 获取数据源DataSource对象. 可以直接创建ComboPooledDataSource对象后调用相应的set方法, 如:
ComboPooledDataSource pool = new ComboPooledDataSource();
pool.setJdbcUrl("jdbc:mysql://localhost:3306/exercise");
pool.setUser("root");
pool.setPassword("root");
pool.setDriverClass("com.mysql.jdbc.Driver");
pool.setInitialPoolSize(10);
也可以在创建ComboPooledDataSource对象时传入配置节点的名称, 此时需要存在c3p0-config.xml文件. 如:
// 创建连接池, 并从c3p0-config.xml文件中的name属性为mysql的named-config元素中读取参数
ComboPooledDataSource pool = new ComboPooledDataSource("mysql");
c. 调用DataSource对象的getConnection()方法获得连接.
- 自定义JDBC连接池及常用连接池介绍
- 自定义jdbc连接池
- jdbc----自定义连接池
- Jdbc连接池介绍
- Jdbc连接池介绍
- java JDBC 自定义连接池
- jdbc连接池及配置
- JDBC学习03-自定义连接池
- (一)JDBC连接池&DBUtils—自定义连接池
- 连接池配置c3p0、dbcp、tomcat jdbc pool 及常用数据库的driverClass和驱动包
- JDBC连接池
- JDBC与连接池
- JDBC与连接池
- JDBC连接池实现
- jdbc连接池
- jdbc连接池
- JDBC+MySQL连接池
- jdbc连接池
- windows7下如何使用myeclipse(eclipse)和cvs进行项目管理
- static 简单例子
- QT 线程池 + TCP 小试(一)线程池的简单实现
- 各种字符串Hash函数比较
- 最简单的ExtJS4的MVC实例
- 自定义JDBC连接池及常用连接池介绍
- 东子破解2
- EL 表达式
- 使用FFmpeg捕获一帧摄像头图像
- 【Spring】1 Spring IoC容器中组件管理 基础
- 控制反转(IOC)的简单实现及原理分析
- javascript拖动效果的一个注意事项:拖动图片时,mousemove事件会被中断
- C++的#号使用
- 搜索引擎lucene