今日内容介绍
使用DBCP,C3P0连接池完成基本数据库的操作
使用DBUtils完成CRUD的操作
今日内容学习目标
使用C3P0创建数据源DataSource。
使用DBCP创建据源DataSource。
能够使用JDBC简化工具包DBUtils完成单表的增删改查操作。
1.因为每次创建和销毁连接都会带来较大的系统开销
2.每次创建和销毁连接都要消耗大概0.05~1s的时间。
3.可以防止大量用户并发访问数据库服务器。
Connection对象在JDBC使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了.每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化.程序初始化的时候,初始化多个连接,将多个连接放入到池(集合)中.每次获取的时候,都可以直接从连接池中进行获取.使用结束以后,将连接归还到池中.
目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能。
3.1步骤
创建一个类,定义LinkedList集合作为连接池,在静态代码块中,向集合里面添加5个连接对象
添加addBack()方法,用作归还连接
代码:
public class MyDataSource { //连接池 static LinkedListpool = new LinkedList<>(); //初始化连接 static{ try { for(int i = 0;i < 5;i++){ pool.add(JdbcUtils.getConnection()); } } catch (SQLException e) { e.printStackTrace(); } } //定义一个方法,从池子中获取connection,从头部获取 public Connection getConnectionFromPool(){ if (pool.size() > 0) { //池子中有connection return pool.removeFirst(); }else { //如果池子中没有connection,则先加入等待队列,等待队列满了的话就新建connection(新建的 //connection是不需要放回池子的,用完后直接销毁) return JDBCUtil.getConnection(); } } //定义一个方法,将connection放回池子中(如果是新创建的connection则直接销毁) public void addBack(Connection connection){ //pool.addLast(connection);//免不了会将新建的connection添加进池子; try { //写一个自己的connection,然后重写close()方法,通过close()方法来添加进池子。 connection.close();//免不了会将池子中的connection销毁 } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //返回pool里面连接的个数 public int getCount(){ return pool.size(); } }
3.2编写连接池遇到的问题
如果新建了connection,用完之后怎么判别是原池子中的connection(需要放回去),还是新建的connection(需要销毁)。
3.3解决办法(自定义一个Connection,重写close方法)
继承条件:可以控制父类的构造
装饰者模式
目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
条件:1.包装类和被包装类实现的是同一个接口 2.包装类里面要拿到被包装类的引用
步骤:
编写一个类实现一个接口,为被包装类
编写一个类,实现与被包装类相同的接口。(具备相同的行为)
定义一个被包装类类型的变量。
定义构造方法,把被包装类类的对象注入,给被包装类变量赋值。
对于不需要改写的方法,调用被包装类类原有的方法。
对于需要改写的方法,写自己的代码。
动态代理(类似装饰者模式,此处不学)
3.4datasource接口概述
Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商(用户)需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池:DBCP、C3P0。
4.1.1 dbcp概念
DBCP:Apache推出的Database Connection Pool
核心API:
basicDatasource
basicDatasourceFactory
4.1.2使用步骤
添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
添加配置文件到src目录
编写数据源工具类
通过配置文件来编写
public class DBCPUtils { static DataSource ds; static { //只需要初始化一次 try { Properties p = new Properties(); InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); // InputStream is = new FileInputStream("src/dbcpconfig.properties"); p.load(is); ds = BasicDataSourceFactory.createDataSource(p); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 创建连接 public static Connection getConnection() throws SQLException { // DriverManager.getConnection(url, user, password); Connection Connection connection = ds.getConnection(); return connection; } // 释放资源 public static void release(ResultSet resultSet, Statement statement, Connection connection) { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close();//不要关注方法名,关注连接来源 } catch (SQLException e) { e.printStackTrace(); } } } }
通过硬编码来表写(不需要配置文件.了解一下)
DataSource basicDataSource = new BasicDataSource(); basicDataSource.setDriverClassName("com.mysql.jdbc.Driver"); basicDataSource.setUrl("jdbc:mysql://localhost:3306/day01_1"); basicDataSource.setUsername("root"); basicDataSource.setPassword("123456");
4.2.1 c3p0概念
C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用第三方工具需要导入jar包,c3p0使用时还需要添加配置文件c3p0-config.xml
4.2.2使用步骤
添加jar包
编写配置文件c3p0-config.xml,放在src中(注:文件名一定不要写错)
通过配置文件来编写
public class C3P0Utils { //创建一个连接池对象 static DataSource ds = new ComboPooledDataSource(); //从池中获得一个连接 public static Connection getConnection() throws SQLException{ return ds.getConnection(); } //释放资源 public static void release(ResultSet rs,Statement stmt,Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { throw new RuntimeException(e); } rs = null; } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { throw new RuntimeException(e); } stmt = null; } if(conn!=null){ try { conn.close();//放心的关。是否关闭取决连接是怎么来的 } catch (SQLException e) { throw new RuntimeException(e); } conn = null; } } }
通过硬编码来编写(不需要配置文件.了解一下)
DataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass("com.mysql.jdbc.Driver"); // loads the jdbc driver cpds.setJdbcUrl("jdbc:mysql://localhost:3306/day10"); cpds.setUser("root"); cpds.setPassword("123");
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
druid连接池的使用
使用硬编码方式
//创建一个DruidDataSource()对象 DruidDataSource dataSource = new DruidDataSource(); //设置用户名 dataSource.setUsername("root"); //设置密码 dataSource.setPassword("123"); //设置驱动类名 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); //设置初始化连接数 dataSource.setInitialSize(10); //获得连接 Connection connection = dataSource.getConnection();
使用配置文件
//创建Properties对象
Properties properties = new Properties(); //加载配置文件 properties.load(new FileInputStream("src/druidconfig.properties")); //创建使用连接池工厂创建连接池 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); //获得连接 Connection connection = dataSource.getConnection();
简化JDBC代码开发,本案例我们将采用apache commons组件一个成员:DBUtils。
DBUtils就是JDBC的简化开发工具包。需要使用技术:连接池(获得连接)、SQL语句都没有少
JavaBean就是一个类,在开发中常用于封装数据。具有如下特性
1.需要实现接口:java.io.Serializable ,通常偷懒省略了。2.提供私有字段:private 类型 字段名;3.提供getter/setter方法:4.提供无参构造
public class Category { private String cid; private String cname; public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } }
DBUtils是java编程中的数据库操作实用工具,小巧简单实用。 第一个操作数据库框架(jar),
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
Dbutils三个核心功能介绍
QueryRunner中提供对sql语句操作的API. update(), query()
ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法
QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection
update(String sql, Object... params) ,执行更新数据 insert update delete 参数就是一个数组,参数个数取决于语句中?的个数
query(String sql, ResultSetHandler
Handler类型 | 说明 |
---|---|
ArrayHandler | 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值 |
ArrayListHandler | 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。 |
BeanHandler | 将结果集中第一条记录封装到一个指定的javaBean中。 |
BeanListHandler | 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中 |
ColumnListHandler | 将结果集中指定的列的字段值,封装到一个List集合中 |
KeyedHandler | 将结果集中每一条记录封装到Map |
MapHandler | 将结果集中第一条记录封装到了Map |
MapListHandler | 将结果集中每一条记录封装到了Map |
ScalarHandler | 它是用于单个数据。例如select count(*) from 表操作。 |
创建项目,并导入jar包
创建连接池
编写测试类
//向user表添加一条数据 @Test public void insert() throws SQLException{ //创建queryRunner对象 QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); //String sql = "insert into user values(null,'aaa','111','露西')"; String sql = "insert into user values(?,?,?,?)"; Object[] params ={null,"aaa","111","露西"}; queryRunner.update(sql, params); }
//把用户名是aaa的user密码改成222 @Test public void update() throws SQLException{ //创建queryRunner对象 QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); String sql = "update user set password = ? where username = ?"; Object[] params={"222","aaa"}; queryRunner.update(sql, params); }
//把用户名是aaa的user给删除 @Test public void delete() throws SQLException{ //创建queryRunner对象 QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); String sql = "delete from user where username = ?"; Object[] params={"aaa"}; queryRunner.update(sql, params); }
//查询id为1的用户信息 @Test public void selectById() throws SQLException{ //创建queryRunner对象 QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); String sql = "select *from user where id = ?"; Object[] params = {1}; User user = queryRunner.query(sql, new BeanHandler<>(User.class), params); System.out.println(user.toString()); }
//查询所有的用户信息 @Test public void selectAll() throws SQLException{ //创建queryRunner对象 QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); String sql = "select *from user"; Object[] params = {}; Listlist = queryRunner.query(sql, new BeanListHandler<>(User.class), params); System.out.println(list.toString()); }
//统计用户的个数 @Test public void getCount() throws SQLException{ //创建queryRunner对象 QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); String sql = "select count(*) from user"; Long n = (Long) queryRunner.query(sql, new ScalarHandler()); System.out.println(n.intValue()); }
最基本的要求:
1.会使用DBCP、C3P0、Druid连接池。
2.会使用DBUtils