数据库连接池 DBCP数据源 DBCP是数据库连接池(DataBase Connection Pool)的简称,是Apache组织下的开源连接池实现,也是Tomcat服务器使用的连接池组件。单独使用DBCP数据源时,需要在应用程序 中导入两个JAR包,具体如下。 1.commons-dbcp.jar包 commons-dbcp.jar包是DBCP数据源的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了DataSource接口的getConnection()方法。 2. commons-pool.jar包 commons-pool.jar包是DBCP数据库连接池实现包的依赖包,为commons-dbcp.jar包中的方法提供了支持。可以这么说,没有该依赖包,commons-dbcp.jar包中的很多方法就没有办法实现。
1.在chapter13.example下创建一个Example01类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package chapter13.example; import java.awt.image.DataBufferShort; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import java.sql.DatabaseMetaData; import java.sql.Connection; public class example01 { public static DataSource ds = null ; static { BasicDataSource bds = new BasicDataSource(); bds.setDriverClassName("com.mysql.cj.jdbc.Driver" ); bds.setUrl( "jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC" ); bds.setUsername("root" ); bds.setPassword("123456" ); 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()); } }
通过读取配置文件创建数据源对象 除了使用BasicDataSource 直接创建数据源对象外,还可以使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后获取数据库连接对象。 (1)在chapter10项目的src目录下创建dbcpconfig.properties文件,该文件用于设置数据库的连接信息和数据源的初始化信息
1 2 3 4 5 6 7 8 9 10 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql: username=root password=123456 initialSize=5 maxActive=10 maxIdle=10
(2)在pidan.example包下创建一个Example02类,该类中采用了从配置文件中获取数据库的连接信息和数据源的初始化信息的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package baixiao.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()); } }
通过 ComboPooledDataSource()构造方法创建数据源对象 (1)在项目chapter10中导入JAR包c3p0-0.9.1.2.jar,然后在cn.itcast.chapter10.example 包下创建一个Example03类,该类采用C3PO数据源手动代码的方式获取Connection对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 **package baixiao.example; import java.sql.SQLException;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource; public class Example03 { public static DataSource ds= null ; static { ComboPooledDataSource cpds = new ComboPooledDataSource(); try { cpds.setDriverClass("com.mysql.jdbc.Driver" ); cpds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc" ); cpds.setUser("root" ); cpds.setPassword("123456" ); 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()); } }
通过读取配置文件创建数据源对象 使用 ComboPooledDataSource(String configName)构造方法读取c3p0-config.xml配 置文件,从而创建数据源对象,然后获取数据库连接对象。 (1)在src根目录下创建一个c3p0-config.xml文件,用于设置数据库的连接信息和数据源的初始化信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?xml version="1.0" encoding="UTF-8" ?> <c3p0-config> <default -config> <property name="driverClass" >com.mysql.jdbc.Driver</property> <property name="jdbcUrl" > jdbc:mysql: </property> <property name="user" >root</property> <property name="password" >123456 </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="pidan" > <property name="driverClass" >com.mysql.jdbc.Driver</property> <property name="jdbcUrl" > jdbc:mysql: </property> <property name="user" >root</property> <property name="password" >123456 </property> <property name="initialPoolSize" >5 </property> <property name="maxPoolSize" >15 </property> </named-config> </c3p0-config>
c3p0-config.xml 配置了两套数据源,.… 中的信息是默认配置,在没有指定配置时默认使用该配置创建C3p0数据源对象;…</ named-config >中的信息是自定义配置, 一个配置文件中可以有零个或多个自定义配置,当用户需要使用自定义配置时,调用ComboPooledDataSource(String configName)方法,传入节点中name属性的值即可创建C3PO数据源对象。这种设置的好处是,当程序在后期更换数据源配置时,只需要修改构造方法中对应的name值即可。 (2)在pidan.example包下创建一个Example04类,该类中使用C3P0数据源从配置文件中获取Connection对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package baixiao.example; import java.sql.SQLException;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource; public class Example04 { public static DataSource ds= null ; static { ComboPooledDataSource cpds = new ComboPooledDataSource("pidan" ); ds = cpds; } public static void main (String[] args) throws SQLException { System.out.println(ds.getConnection()); } }
DBUtils 工具
BeanHandler 和 BeanListHandler BeanHandler和BeanListHandler实现类是将结果集中的数据封装到对应的JavaBean实例中,这也是实际开发中最常用的结果集处理方法。
(1)在名为jdbc的数据库中创建数据表user,创建语句如下。
1 2 3 4 5 6 USE jdbc; CREATE TABLE user ( id INT(3 ) PRIMARY KEY AUTO_INCREMENT,name VARCHAR (20 ) NOT NULL, password VARCHAR (20 ) NOT NULL ) ;
向user表插入3条数据,具体语句如下
1 2 3 INSERT INTO user (name, password) VALUES ('zhangsan' ,'123456' ) ;INSERT INTO user (name, password) VALUES ('lisi' ,'123456' ) ;INSERT INTO user (name, password) VALUES ('wangwu' ,'123456' ) ;
(2)将下载的DBUtils 工具的JAR包commons-dbutils-1.6.jar添加到项目的 lib目录中,并将第9章中文件JDBCUtils.java复制到pidan.example包下。
(3)在chapter10项目的pidan.example包中创建一个名为BaseDao的类,该类中编写了一个通用的查询方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package baixiao.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(); pstmt = conn.prepareStatement(sql); for (int i = 0 ; params != null && i < params.length; i++) { pstmt.setObject(i+1 , params[i]); } rs = pstmt.executeQuery(); obj = rsh.handle(rs); } catch (Exception e) { return new Exception(e.getMessage()); }finally { JDBCUtils.release(rs, pstmt,conn); } return obj; } }****
(4)在pidan.example包下创建实体类User,使用该类来封装User对象(建议自己getset)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package baixiao.example; public class User { private int id; private String name,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)在 pidan.example包下创建类ResultSetTest1,该类用于演示BeanHandler类对结果集的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package baixiao.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 ); if (object!=null && object instanceof User) { User user = (User) object; System.out.println("id=1的User对象的name值为:" + user.getName()); }else { System.out.println("查询结果为空:" +object); } } public static void main (String[] args) throws SQLException { testBeanHandler(); } }
(7)在pidan.example包下创建类ResultSetTest2,该类用于演示BeanListHandler类对结果集的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package baixiao.example; import java.sql.SQLException;import java.util.ArrayList; import org.apache.commons.dbutils.handlers.BeanListHandler; public class ResultSetTest2 { public static void testBeanHandler () 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 { testBeanHandler(); } }
(8)执行类ResultSetTest2中的main()方法
ScalarHandler 在使用DBUtils工具操作数据库时,如果需要输出结果集中一行数据的指定字段值,可以使用ScalarHandler类。 (1)在 baixiao.example 包下创建类 ResultSetTest3,该类用于演示 ScalarHandler类的使用方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package baixiao.example; import java.sql.SQLException; import org.apache.commons.dbutils.handlers.ScalarHandler; public class ResultSetTest3 { public static void testBeanHandler () 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 { testBeanHandler(); } }
创建DBUtilsDao类 在项目chapter10的src目录下,创建一个名为pidan.jdbc.demo的包,然后在该包下创建一个DBUtilsDao类,该类实现了对user表增删改查的基本操作。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package baixiao.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 pidan.example.User;import pidan.jdbc.utils.C3p0Utils; public class DBUtilsDao { public List findAll () throws SQLException { QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource()); 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 runner = new QueryRunner(C3p0Utils.getDataSource()); 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 runner = new QueryRunner(C3p0Utils.getDataSource()); 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 updata (User user) throws SQLException { QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource()); 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 runner = new QueryRunner(C3p0Utils.getDataSource()); String sql = "delete from user where id=?" ; int num = runner.update(sql,id); if (num > 0 ) { return true ; } return false ; } }
上述代码中,使用了QueryRunner类中带参的方法,将数据源传给QueryRunner对象,并使用QuervRunner对象创建和关闭了数据库连接。 这样,就实现了用DBUtils工具对数据库的基本操作。需要注意的是,在查询方法中,用到了 BeanHandler和BeanListHandler实现类来处理结果集, 查询一条数据用的是能够处理一行数据的BeanHandler类,查询所有数据时用的是能处理所有行数据的BeanListHandler类,切勿错误使用,否则会造成程序报错。
3.测试DBUtilsDao类中的增删改查操作 (1)增加数据。在 baixiao.jdbc.demo包中创建类DBUtilsDaoTest1对增加操作进行测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package baixiao.jdbc.demo; import java.sql.SQLException; import pidan.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)修改数据。在baixiao.jdbc.demo包下创建测试类DBUtilsDaoTest2。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package baixiao.jdbc.demo; import java.sql.SQLException; import pidan.example.User; public class DBUtilsDaoTest2 { private static DBUtilsDao dao = new DBUtilsDao(); public static void testupdate () throws SQLException { User user = new User(); user.setName("zhaoliou" ); user.setPassword("666777" ); user.setId(4 ); boolean b = dao.updata(user); System.out.println(b); } public static void main (String[] args) throws SQLException { testupdate(); } }
(3)删除数据。在baixiao.jdbc.demo包下创建测试类DBUtilsDaoTest3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package baixiao.jdbc.demo; import java.sql.SQLException; import pidan.example.User; public class DBUtilsDaoTest3 { private static DBUtilsDao dao = new DBUtilsDao(); public static void testupdate () throws SQLException { boolean b = dao.delete(4 ); System.out.println(b); } public static void main (String[] args) throws SQLException { testupdate(); } }
(4)查询数据。在baixiao.jdbc.demo包下创建测试类DBUtilsDaoTest4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package baixiao.jdbc.demo; import java.sql.SQLException; import pidan.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(); } }