Advertisement

数据库连接池与DBUtils工具

阅读量:

数据库连接池,简称dbcp database connection pool
数据库的连接是非常耗费系统资源的,一个应用通常都是需要与数据库打交道,也就需要经常连接数据库,这样导致浪费大量系统资源;
连接池的原理就是:
我事先创建好几个数据库连接放着,当我的系统需要操作数据库时就从连接池里直接拿连接,并将这个连接标记为 忙 ;用完后在放会池中,标记为 空闲;
当连接池里的连接都在被使用,如果此时还要连接,连接池就会在创建连接放到池里,,这些连接的数量,都是在配置文件里由我控制的。
数据库连接池的运行机制:
(1) 程序初始化时创建连接池
(2) 使用时向连接池申请可用连接
(3) 使用完毕,将连接返还给连接池
(4) 程序退出时,断开所有连接,并释放资源
在这里插入图片描述
为了获取数据库连接对象(Connection),JDBC提供了javax.sql.DataSource接口,它负责与数据库建立连接,并定义返回值为Connection对象的方法。例:
Connection getConnection() 通过无参的方式建立与数据库的连接;
Connection getConnection(String username, String password) 通过传入登录信息的方式与数据库的连接。
在使用DBCP数据源时,需要导入:
commons-dbcp.jar包(它是DBCP数据源的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了DataSource接口的getConnection()方法);
commons-pool.jar包 (它是DBCP数据库连接池实现包的依赖包,为commons-dbcp,jar包中的方法提供了支持)。
BasicDataSource是DataSource接口的实现类,主要包括设置数据源对象的方法,常用方法有:
void setDriverClassName(String driverClassName) (设置连接数据库的驱动名称)
void setUrl(String url) (设置连接数据库的路径)
void setUsername(String username) (设置数据库的登录账号)
void setPassword(String password) (设置数据库的登录密码)
void setInitialSize(int initialSize) (设置数据库连接池初始化的连接数目)
void setMaxActive(int maxldle) (设置数据库连接池最大活跃的连接数目)
void setMinldle(int minldle) (设置数据库连接池最小闲置的连接数目)
Connection getConnection() (从连接池中获取一个数据库连接)
BasicDataSourceFactory是创建BasicDataSource 对象的工厂类,它包含一一个返回值为BasicDataSource对象的方法createDataSource(),该方法通过读取配置文件的信息生成数据源对象并返回给调用者。这种把数据库的连接信息和数据源的初始化信息提取出来写进配置文件的方式,让代码看起来更加简洁,思路也更加清晰。
1.通过BasicDataSource类直接创建数据源对象
(1)在Eclipse 中创建一一个名称为chapter10 的Web项目,在项目chapter10中导入mysql-connector-java- 5.0.8-bin.jar、commons- -dbcp-1.4.jar以及commons -pool-1.6.jar 3个JAR包,并发布到类路径下,然后在项目的src目录下创建包cn.itcast.chapter 10.example,并在该包下创建一个Example01类,该类采用手动方式获取数据库的连接信息和数据源的初始化信息:
Example01.java

复制代码
    package cn.itcast.chapter10.example;
    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.SQLException;
    import javax.sql.DataSource;
    import org.apache.commons.dbcp.BasicDataSource;
    public class Example01 {
    	public static DataSource ds = null;
    	static {
    		// 获取DBCP数据源实现类对象
    		BasicDataSource bds = new BasicDataSource();
    		// 设置连接数据库需要的配置信息
    		bds.setDriverClassName("com.mysql.jdbc.Driver");
    		bds.setUrl("jdbc:mysql://localhost:3306/jdbc");
    		bds.setUsername("root");
    		bds.setPassword("itcast");
    		// 设置连接池的参数
    		bds.setInitialSize(5);
    		bds.setMaxActive(5);
    		ds = bds;
    	}
    	public static void main(String[] args) throws SQLException {
    		// 获取数据库连接对象
    		Connection conn = ds.getConnection();
    		//获取数据库连接信息
    		DatabaseMetaData metaData = conn.getMetaData();
    		//打印数据库连接信息
    		System.out.println(metaData.getURL()
             +",UserName="+metaData.getUserName()
             +","+metaData.getDriverName());
    	}
    }

(3)运行main()方法:
jdbc:mysql://localhost:3306/jdbc,UserName=root@localhost,MySQL-AB JDBC Driver
2.通过读取配置文件创建数据源对象:
(1)在chapter10项目的src目录下创建dbcpconfig.properties文件,用于设置数据库的连接信息和数据源的初始化信息:
dbcpconfig.properties

复制代码
     #连接设置
     driverClassName=com.mysql.jdbc.Driver
     url=jdbc:mysql://localhost:3306/jdbc
     username=root
     password=itcast
     #初始化连接
     initialSize=5
     #最大连接数量
     maxActive=10
     #最大空闲连接
     maxIdle=10

(2)在cn.itcast.chapter10.example包下创建一个Example02类,从配置文件中获取数据库的连接信息和数据源的初始化信息:
Example02.java

复制代码
    package cn.itcast.chapter10.example;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.SQLException;
    import java.util.Properties;
    import javax.sql.DataSource;
    import org.apache.commons.dbcp.BasicDataSourceFactory;
    public class Example02 {
    	public static DataSource ds = null;
    	static {
    		// 新建一个配置文件对象
    		Properties prop = new Properties();
    		try {
    			// 通过类加载器找到文件路径,读配置文件
    			InputStream in = new Example02().getClass().getClassLoader()
    					.getResourceAsStream("dbcpconfig.properties");
    			// 把文件以输入流的形式加载到配置对象中
    			prop.load(in);
    			// 创建数据源对象
    			ds = BasicDataSourceFactory.createDataSource(prop);
    		} catch (Exception e) {
    			throw new ExceptionInInitializerError(e);
    		}
    	}
    	public static void main(String[] args) throws SQLException {
    		// 获取数据库连接对象
    		Connection conn = ds.getConnection();
    		//获取数据库连接信息
    		DatabaseMetaData metaData = conn.getMetaData();
    		//打印数据库连接信息
         System.out.println(metaData.getURL()
              +",UserName="+metaData.getUserName()   
                    +","+metaData.getDriverName());	
    }
    }

(3)运行main()方法:
jdbc:mysql://localhost:3306/jdbc,UserName=root@localhost,MySQL-AB JDBC Driver
C3P0数据源是目前最流行的开源数据库连接池之一,它实现了DataSource数据源接口,支持JDBC2和JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架Hibernate和Spring都支持该数据源。
ComboPooledDataSource类的常用方法:
void setDriverClass() (设置连接数据库的驱动名称)
void setJdbcUrl() (设置连接数据库的路径)
void setUser() (设置数据库的登录账号)
void setPassword() (设置数据库的登录密码)
void setMaxPoolSize() (设置数据库连接池最大的连接数目)
void setMinPoolSize() (设置数据库连接池最小的连接数目)
void setInitialPoolSize() (设置数据库连接池初始化的连接数目)
Connection getconnection() (从数据库连接池中获取一个连接)
1.通过ComboPooledDataSource()构造方法创建数据源对象
(1)在项目chapter10中导入JAR包c3p0-0.9.12.jar,然后在cn.itcast.chapter10.example包下创建一个Example03类,使用C3P0数据源手动代码的方式获取Connection对象:
Example03.java

复制代码
    package cn.itcast.chapter10.example;
    import java.sql.SQLException;
    import javax.sql.DataSource;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    public class Example03 {
    	public static DataSource ds = null;
    	// 初始化C3P0数据源
    	static {
    		ComboPooledDataSource cpds = new ComboPooledDataSource();
    		// 设置连接数据库需要的配置信息
    		try {
    			cpds.setDriverClass("com.mysql.jdbc.Driver");
    			cpds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc");
    			cpds.setUser("root");
    			cpds.setPassword("itcast");
    			// 设置连接池的参数
    			cpds.setInitialPoolSize(5);
    			cpds.setMaxPoolSize(15);
    			ds = cpds;
    		} catch (Exception e) {
    			throw new ExceptionInInitializerError(e);
    		}
    	}
    	public static void main(String[] args) throws SQLException {
    		// 获取数据库连接对象
    		System.out.println(ds.getConnection());
    	}
    }

(2)执行main()方法:
com.mchange.v2.c3p0.imp1.NewProxyConnection@1fa5d1a
2.通过读取配置文件创建数据源对象
(1)在src根目录下创建一个c3p0-config.xml,设置数据库的连接信息和数据源的初始化信息:
c3p0-config.xml

复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    	<default-config>
    		<property name="driverClass">com.mysql.jdbc.Driver</property>
    		<property name="jdbcUrl">
     		jdbc:mysql://localhost:3306/jdbc
     	</property>
    		<property name="user">root</property>
    		<property name="password">itcast</property>
    		<property name="checkoutTimeout">30000</property>
    		<property name="initialPoolSize">10</property>
    		<property name="maxIdleTime">30</property>
    		<property name="maxPoolSize">100</property>
    		<property name="minPoolSize">10</property>
    		<property name="maxStatements">200</property>
    	</default-config> 
    	<named-config name="itcast">
    		<property name="driverClass">com.mysql.jdbc.Driver</property>
    		<property name="jdbcUrl">
           	jdbc:mysql://localhost:3306/jdbc
        </property>
    		<property name="user">root</property>
    		<property name="password">itcast</property>
    		<property name="initialPoolSize">5</property>
    		<property name="maxPoolSize">15</property>
    	</named-config>
    </c3p0-config>

(2)在cn.itcast.chapter10.example包下创建一个Example04类,使用C3P0数据源从配置文件中获取Connection对象:
Example04.java

复制代码
     package cn.itcast.chapter10.example;
     import java.sql.SQLException;
     import javax.sql.DataSource;
     import com.mchange.v2.c3p0.ComboPooledDataSource;
     public class Example04 {
     	public static DataSource ds = null;
     	// 初始化C3P0数据源
     	static {
     		// 使用c3p0-config.xml配置文件中的named-config节点中name属性的值
     		ComboPooledDataSource cpds = new ComboPooledDataSource("itcast");
     		ds = cpds;
     	}
     	public static void main(String[] args) throws SQLException {
     		System.out.println(ds.getConnection());
     	}
     }

(3)执行main()方法:
com.mchange.v2.c3p0.imp1.NewProxyConnection@14ec310
DBUtils工具:
QueryRunner类简化了执行SQL语句的代码,它与ResultSelHandler组合在一起就能完成大部分的数据库操作,大大地减少了编码量。
QueryRunner类提供了带有一个参 数的构造方法,该方法以javax.sql.DataSource作为参数传递到QueryRunner的构造方法中来获取Connection对象。针对不同的数据库操作,QueryRunner类提供了几种常见的方法,具体如下:.
query(String sql, ResultSetHandler rsh, bjet… params) (该方法用于执行查询操作,它可以从提供给构造方法的数据源DataSource 或使用的setDataSource()方法中获得连接)
update(String sql, Obiet… params) (该方法用于执行插入、更新或者删除操作,其中,参数parans表示SQL语句中的置换参数)
update(String sq|) (该方法用来执行插入、更新或者删除操作,它不需要置换参数)

ResultSetHandler接口
ResultSetHandler接口用于处理ResultSet结果集,它可以将结果集中的数据转为不同的形
式。根据结果集中数据类型的不同,ResultSetHandler提供了几种常见的实现类,具体如下。
BeanHander: 将结果集中的第1行数据封装到一个对应的JavaBean实例中。
Beanl istHandler:将结果集中的每行数据都封装到一个对应的JavaBean实例中,并
存放到List里。
ScalarHandler: 将结果集中某一 条记录的其中某一 列的数据存储成Object对象。

ResultSetHandler实现类

1.BeanHandler 和BeanL istHandler
BeanHandler和BeanListHandler实现类是将结果集中的数据封装到对应的JavaBean实例
中,这也是实际开发中最常用的结果集处理方法。
(1)在名为jdbc的数据库中创建数据表user, 创建语句如下。

复制代码
    USE jdbc;
    CREATE TABLE user (
    	id INT(3) PRIMARY KEY AUTO_INCREMENT,
    	name VARCHAR(20) NOT NULL,
    	password VARCHAR(20) NOT NULL
    );

向user表插入3条数据,具体语句如下。

复制代码
    INSERT INTO user (name ,password) VALUES (' zhangsan', '123456');
    INSERT INTO user (namepassword) VALUES ('1i81', '123456');
    INSERT INTO user (name,password) VALUES ('wangwu', '123456');

为了查看数据是否添加成功,使用SELECET语句查询user表:
在这里插入图片描述
(2)将DBUtils工具的JAR包commons-dbutils-1.6.jar添加到项目的lib目录中
(3)在chapter10项目cn.itcast.chapter10.example包中创建一个名为BaseDao的类,编写一个通用的查询方法:
BaseDao.java

复制代码
    package cn.itcast.chapter10.example;
    import java.sql.Connection;                                                                                                                                             
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import org.apache.commons.dbutils.ResultSetHandler;
    public class BaseDao {
     	// 优化查询
     	public static Object query(String sql, ResultSetHandler<?> rsh, 
    		                       Object... params) throws SQLException {
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		ResultSet rs = null;
    		// 定义一个返回结果
    		Object obj = null;
    		try {
    			// 获得连接
    			conn = JDBCUtils.getConnection();
    			// 预编译sql
    			pstmt = conn.prepareStatement(sql);
    			// 将参数设置进去
    			for (int i = 0; params != null && i < params.length; i++)
    			  {
    				pstmt.setObject(i + 1, params[i]);
    			}
    			// 发送sql
    			rs = pstmt.executeQuery();
    			// 让调用者去实现对结果集的处理
    			obj = rsh.handle(rs);
    		} catch (Exception e) {
    			// 出现异常,返回封装的异常信息
    			return new Exception(e.getMessage());
    		}finally {
    			// 释放资源
    			JDBCUtils.release(rs, pstmt, conn);
    		}
    		return obj;
     	}
    }

(4)在cn.itcast.chapter10.example包下创建实体类User,用来封装User对象:
User.java

复制代码
    package cn.itcast.chapter10.example;
    public class User {
    	private int id;
    	private String name;
    	private String password;
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    }

(5)在cn.itcast.chapter10.example包下创建类ResultSetTest1,用于演示BeanHandler类对结果集的处理:
ResultSetTest1.java

复制代码
    package cn.itcast.chapter10.example;
    import java.sql.SQLException;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    public class ResultSetTest1 {
    	public static void testBeanHandler() throws SQLException {
    		BaseDao basedao = new BaseDao();
    		String sql = "select * from user where id=?";
    		// 获取查询结果
    		Object object = basedao.query(sql, new BeanHandler(User.class), 1);
    		// 判断查询结果,如果是User类就进行打印,否则打印查询的结果信息
    		if (object!=null && object instanceof User){
    			User user= (User) object;
    			System.out.print("id为1的User对象的name值为:" + user.getName());
    		}else {
    			System.out.println("查询结果为空: "+object);
    		}
    	}
    	public static void main(String[] args) throws SQLException {
    		testBeanHandler();
    	}
    }

(6)执行ResultSetTest1中的main()方法:
id为1的User对象的name值为:zhangyanju
(7)在cn.itcast.chapter10.example包下创建类ResultSetTest2,用于演示BeanListHandler类对结果集的处理:
ResultSetTest2.java

复制代码
    package cn.itcast.chapter10.example;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    public class ResultSetTest2 {
    	public static void testBeanListHandler() throws SQLException {
    		BaseDao basedao = new BaseDao();
    		String sql = "select * from user ";
    		ArrayList<User> list = (ArrayList<User>) basedao.query(sql,
    				new BeanListHandler(User.class));
    		for (int i = 0; i < list.size(); i++) {
    			System.out.println("第" + (i + 1) + "条数据的username值为:"
    					+ list.get(i).getName());
    		}
    	}
    	public static void main(String[] args) throws SQLException {
    		testBeanListHandler();
    	}
    }

(8)执行ResultSetTest2中的main()方法:
第1条数据的username值为:zhangyanju
第2条数据的username值为:yiyi
第3条数据的username值为:lili
2.ScalarHandler
(1)在cn.itcast.chapter10.example包下创建类ResultSetTest3,用于演示ScalarHandler类的使用方法:
ResultSetTest3.java

复制代码
    package cn.itcast.chapter10.example;
    import java.sql.SQLException;
    import org.apache.commons.dbutils.handlers.ScalarHandler;
    public class ResultSetTest3 {
    public static void testScalarHandler() throws SQLException {
    	BaseDao basedao = new BaseDao();
    	String sql = "select * from user where id=?";
    	Object arr = (Object) basedao.query(sql, 
                           new ScalarHandler("name"), 1);
    		System.out.println(arr);
    	}
    	public static void main(String[] args) throws SQLException {
    		testScalarHandler();
    	}
    }

(2)执行ResultSetTest3中的main()方法:
zhangyanju
使用DBUtils实现增删改查
1.在项目chapter10的src目录下,创建一个名为cn.itcast.jdbc.utils的包,然后在该包下创建C3p0Utils类,用于创建数据源:
C3p0Utils.java

复制代码
    package cn.itcast.jdbc.utils;
    import javax.sql.DataSource;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    public class C3p0Utils {
    	private static DataSource ds;
    	static {
    		ds = new ComboPooledDataSource();
    	}
    	public static DataSource getDataSource() {
    		return ds;
    	}
    }

2.在项目chapter10的src目录下,创建一个名为cn.itcast.jdbc.demo的包,然后在该包下创建DBUtilsDao类,用于实现对user表增删改查的基本操作:
DBUtilsDao.java

复制代码
    package cn.itcast.jdbc.demo;
    import java.sql.SQLException;
    import java.util.List;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import cn.itcast.chapter10.example.User;
    import cn.itcast.jdbc.utils.C3p0Utils;
    public class DBUtilsDao {
    	// 查询所有,返回List集合
    	public List findAll() throws SQLException {
    		// 创建QueryRunner对象
    		QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
    		// 写SQL语句
    		String sql = "select * from user";
    		// 调用方法
    		List list = (List) runner.query(sql,
                     new BeanListHandler(User.class));
    		return list;
    	}
    	// 查询单个,返回对象
    	public User find(int id) throws SQLException {
    		// 创建QueryRunner对象
    		QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
    		// 写SQL语句
    		String sql = "select * from user where id=?";
    		// 调用方法
    		User user = (User) runner.query(sql, 
                 new BeanHandler(User.class), new Object[] { id });
    		return user;
    	}
    	// 添加用户的操作
    	public Boolean insert(User user) throws SQLException {
    		// 创建QueryRunner对象
    		QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
    		// 写SQL语句
    		String sql = "insert into user (name,password) values (?,?)";
    		// 调用方法
    		int num = runner.update(sql,
    				new Object[] { user.getName(), user.getPassword() });
    		if (num > 0)
    			return true;
    		return false;
    	}
    	// 修改用户的操作
    	public Boolean update(User user) throws SQLException {
    		// 创建QueryRunner对象
    		QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
    		// 写SQL语句
    		String sql = "update  user set name=?,password=? where id=?";
    		// 调用方法
    		int num = runner.update(sql, new Object[] { user.getName(),
                     user.getPassword(),user.getId() });
    		if (num > 0)
    			return true;
    		return false;
    	}
    	// 删除用户的操作
    	public Boolean delete(int id) throws SQLException {
    		// 创建QueryRunner对象
    		QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
    		// 写SQL语句
    		String sql = "delete from user where id=?";
    		// 调用方法
    		int num = runner.update(sql, id);
    		if (num > 0)
    			return true;
    		return false;
    	}
    }

3.测试DBUtilsDao类中的增删改查操作:
(1)在cn.itcast.jdbc.demo包中创建类DBUtilsDaoTest1对增加操作进行测试:
DBUtilsDaoTest1.java

复制代码
    package cn.itcast.jdbc.demo;
    import java.sql.SQLException;
    import cn.itcast.chapter10.example.User;
    public class DBUtilsDaoTest1 {
    	private static DBUtilsDao dao = new DBUtilsDao();
    	public static void testInsert() throws SQLException {
    		User user = new User();
    		user.setName("zhaoliu");
    		user.setPassword("666666");
    		boolean b = dao.insert(user);
    		System.out.println(b);
    	}
    	public static void main(String[] args) throws SQLException {
    		testInsert();
    	}
    }

(2)在cn.itcast.jdbc.demo包中创建类DBUtilsDaoTest2对修改操作进行测试:
DBUtilsDaoTest2.java

复制代码
    package cn.itcast.jdbc.demo;
    import java.sql.SQLException;
    import cn.itcast.chapter10.example.User;
    public class DBUtilsDaoTest2 {
    	private static DBUtilsDao dao = new DBUtilsDao();
    	public static void testupdate() throws SQLException {
    		User user = new User();
    		user.setName("zhaoliu");
    		user.setPassword("666777");
    		user.setId(4);
    		boolean b = dao.update(user);
    		System.out.println(b);
    	}
    	public static void main(String[] args) throws SQLException {
    		testupdate();
    	}
    }

(3)在cn.itcast.jdbc.demo包中创建类DBUtilsDaoTest3对删除操作进行测试:
DBUtilsDaoTest3.java

复制代码
    package cn.itcast.jdbc.demo;
    import java.sql.SQLException;
    public class DBUtilsDaoTest3 {
    	private static DBUtilsDao dao = new DBUtilsDao();
    	public static void testdelete() throws SQLException {
    		boolean b = dao.delete(4);
    		System.out.println(b);
    	}
    	public static void main(String[] args) throws SQLException {
    		testdelete();
    	}
    }

(4)在cn.itcast.jdbc.demo包中创建类DBUtilsDaoTest4对查询操作进行测试:
DBUtilsDaoTest4.java

复制代码
    package cn.itcast.jdbc.demo;
    import java.sql.SQLException;
    import cn.itcast.chapter10.example.User;
    public class DBUtilsDaoTest4 {
    	private static DBUtilsDao dao = new DBUtilsDao();
    	public static void testfind() throws SQLException {
    		User user = dao.find(2);
    		System.out.println(user.getId() + "," + user.getName() + ","
    				+ user.getPassword());
    	}
    	public static void main(String[] args) throws SQLException {
    		testfind();
    	}
    }

全部评论 (0)

还没有任何评论哟~