美文网首页编程语言程序员Java 杂谈
第77节:Java中的事务和数据库连接池和DBUtiles

第77节:Java中的事务和数据库连接池和DBUtiles

作者: 魔王哪吒 | 来源:发表于2019-01-27 15:39 被阅读979次
    标题图

    第77节:Java中的事务和数据库连接池和DBUtiles

    前言

    看哭你,字数:8803,承蒙关照,谢谢朋友点赞!

    字数8803

    事务

    Transaction事务,什么是事务,事务是包含一组操作,这组操作里面包含许多个单一的逻辑,只要有一个逻辑没有执行成功就算失败,导致回滚就是指所有的数据都会回到最初的状态.

    有事务,是为了保证逻辑一定要成功,如银行转账.

    回顾一下

    什么是jsp,jsp的三大指令.

    page: 定义当前页面的信息
    include: 包含其他页面
    taglib: 引入标签库
    

    三大动作标签:

    <jsp:forward page="">:跳转
    <jsp:param name="" value="">:跳转到具体页面或是某个页面被包含的时候,可以指定参数
    <jsp:include page="">:包含
    

    九大内置对象:

    // 四个作用域
    pageContext 当前页
    request 请求 一次请求 响应后就不行了
    session 会话 一次会话
    application 都可以 整个项目,直到关闭服务器
    
    // 5
    response
    out
    exception
    config -> ServletConfig
    page -> this 翻译成java文件的类对象
    

    EL

    ${ 表达式 };
    

    取值

    <% User user = new User(); %>
    ${user.ame}
    从四个作用域里面找 
    pageContext -> request -> session -> application
    
    <%
     User user = new User();
     pageContext.setAttribute("user",user);
    %>
    ${sessionScope.user.name}强制用session找
    

    EL的11个隐式对象:

    pageContext
    // 作用域
    pageScope
    requestScope
    sessionScope
    applicationScope
    
    头相关
    header
    headerValues
    参数
    param
    paramValues
    cookie
    initparam
    

    JSTL

    导包哦,引入标签库是1.1的:

    <c:set>: 存储到作用域
    <c:set var="" value="" scope="">
    <c: if>: 用来判断
    <c:forEach items="" var="">:用于遍历
    

    数据库

    添加两条数据

    数据库命令行:

    命令行 命令行

    关闭自动提交.

    关闭了提交,再减100:

    命令行

    会到数据库查看:

    刷新了

    值没改变!

    输入提交后 刷新改变 开启事务

    添加改变代码:

    先看表
    package com.dashucoding.test;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    import com.dashucoding.util.JDBCUtil;
     
    public class TestDemo { 
        
        @Test
        public void testTransaction() {
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                conn = JDBCUtil.getConn();
                //查询数据
                /*String sql = "select * from account";
                ps = conn.prepareStatement(sql);*/
                
                String sql = "update account set money = money - ? where id = ?";
                ps = conn.prepareStatement(sql);
                
                // 扣钱
                ps.setInt(1, 100);
                ps.setInt(2, 1);
                ps.executeUpdate();
                
                /*ps.setInt(1, -100);
                ps.setInt(2, 1);
                ps.executeUpdate();*/
                
                // 查询数据 
                /*rs = ps.executeQuery();
                while(rs.next()) {
                    System.out.println(rs.getString("name")+"=="+rs.getInt("money"));
                }*/
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, ps, rs);
            }
        }
    }
    
    package com.dashucoding.util;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    public class JDBCUtil {
        
        static String driverClass = null;
        static String url = null;
        static String name = null;
        static String password= null;
        
        static{
            try {
                //1. 创建一个属性配置对象
                Properties properties = new Properties();
                InputStream is = new FileInputStream("jdbc.properties");
                
                
                //使用类加载器,去读取src底下的资源文件。 后面在servlet
    //          InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
                //导入输入流。
                properties.load(is);
                
                //读取属性
                driverClass = properties.getProperty("driverClass");
                url = properties.getProperty("url");
                name = properties.getProperty("name");
                password = properties.getProperty("password");
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 获取连接对象
         * @return
         */
        public static Connection getConn(){
            Connection conn = null;
            try {
                Class.forName(driverClass);
                //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver());
                //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
                //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
                //2. 建立连接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。
                conn = DriverManager.getConnection(url, name, password);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return conn;
        }
        
        /**
         * 释放资源
         * @param conn
         * @param st
         * @param rs
         */
        public static void release(Connection conn , Statement st , ResultSet rs){
            closeRs(rs);
            closeSt(st);
            closeConn(conn);
        }
        public static void release(Connection conn , Statement st){
            closeSt(st);
            closeConn(conn);
        }
    
        
        private static void closeRs(ResultSet rs){
            try {
                if(rs != null){
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                rs = null;
            }
        }
        
        private static void closeSt(Statement st){
            try {
                if(st != null){
                    st.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                st = null;
            }
        }
        
        private static void closeConn(Connection conn){
            try {
                if(conn != null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                conn = null;
            }
        }
    }
    
    刷新后

    事务只针对连接.

    package com.dashucoding.test;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    import com.dashucoding.util.JDBCUtil;
     
    public class TestDemo { 
        
        @Test
        public void test02(){
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                conn = JDBCUtil.getConn();
                
                String sql = "update account set money = money - ? where id = ?";
                ps = conn.prepareStatement(sql);
                
                //扣钱, 扣ID为1 的100块钱
                ps.setInt(1, 100);
                ps.setInt(2, 1);
                ps.executeUpdate();
                
                
                //int a = 10 /0 ;
                String s = null;
                s.length();
                
                //加钱, 给ID为2 加100块钱
                ps.setInt(1, -100);
                ps.setInt(2, 2);
                ps.executeUpdate();
                
                
            } catch (SQLException e) {
                
                e.printStackTrace();
                
            }finally {
                JDBCUtil.release(conn, ps, rs);
            }
        }
        
        @Test
        public void testTransaction() {
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                conn = JDBCUtil.getConn();
                
                // 连接
                conn.setAutoCommit(false);
                
                //查询数据
                /*String sql = "select * from account";
                ps = conn.prepareStatement(sql);*/
                
                String sql = "update account set money = money - ? where id = ?";
                ps = conn.prepareStatement(sql);
                
                // 扣钱
                ps.setInt(1, 100);
                ps.setInt(2, 1);
                ps.executeUpdate();
                
                int a = 10 /0 ;
                
                ps.setInt(1, -100);
                ps.setInt(2, 2);
                ps.executeUpdate();
                
                // 提交事务
                conn.commit();
                
                // 查询数据 
                /*rs = ps.executeQuery();
                while(rs.next()) {
                    System.out.println(rs.getString("name")+"=="+rs.getInt("money"));
                }*/
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                // 回滚事务
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, ps, rs);
            }
        }
    }
    

    事务

    conn.setAutoCommit(false)来关闭自动提交的设置
    conn.commit(); 提交事务
    conn.rollback(); 回滚事务
    

    记住:
    什么是事务,事务有什么用处,事务怎么用.

    事务的特点:

    1. 原子性: 指的是事务中包含的逻辑,不可以分割(事务中逻辑不可分)
    2. 一致性: 事务执行前和执行后,保持数据的完整性一致(执行前后,数据保持一致)
    3. 隔离性: 事务在执行期间不受到其他事务的影响(隔离不受影响)
    4. 持久性: 事务执行结束,提交或回滚,数据都应该持久化到数据中(数据持久化在数据中)

    安全问题

    1. 读问题
      脏读,不可重复读,幻读
    2. 写问题
      丢失更新,解决丢失更新的方法,一悲观锁和乐观锁

    隔离级别

    Read Uncommitted 读未提交
    Read Committed 读已提交
    Repeatable Read 重复读
    Serializable 可串行化
    
    隔离级别

    脏读:

    命令行 效果

    一条连接:


    效果

    另一条连接:


    效果
    use bank;
    start transaction;
    select * from account;
    select * from account;
    
    use bank;
    start transaction;
    update account set money = money + 300 where id = 1;
    commit;
    

    读未提交

    效果

    例子

    命令

    这里查询,然后再看看数据库中的表:

    刷新后

    命令提交:

    命令提交 查询数据

    不可重复读的问题

    效果

    Repeatable Read重复读

    命令 命令 命令

    可串化

    命令 命令

    读未提交,引发脏读,读已提交解决脏读,引发不可重复读, 可重复读解决脏读解决了脏读,不可重复读,

    asss

    小结

    读:
    脏读 不可重读读 幻读

    脏读:
    一个事务读到另外一个事务还未提交的数据

    不可重复读:
    一个事务读到另外一个事务提交的数据,导致前后两次查询结果不一致

    幻读:
    一个事务读到了另外一个事务已提交的插入的数据,导致多次查询结果不一致.

    读未提交,
    会导致丢失更新

    读已提交,
    能够屏蔽 脏读的现象,但是引发不可重复读

    事务的安全隐患脏读

    隔离级别:

    read uncommitted 读未提交
    read committed 读已提交
    repeatable read 重复读
    serializable 可串化
    

    mysql默认的是重复读.

    设置A窗口的隔离级别为 读未提交

    a

    两个窗口都分别开启事务

    脏读 提交后

    读未提交是一个事务可以读取到另一个事务还没有提交的数据,会引发脏读现象,读取到的是数据库内存中的数据,并不是真正的磁盘上的数据.

    还未提交时,数据库内存中的数据是不会改变的,只有到commit提交后,数据库中的数据才会提交,从而读取真正在磁盘上的数据.

    Read Committed读已提交

    命令 命令

    在a发生了变化,屏蔽了脏读,引发不可重复读,读已提交.读已提交,在a窗口设置的是读已提交,两边开启事务.在b窗口更新操作.

    在a窗口查询结果不一致,一次是在b窗口提交事务之前,一次的提交之后.

    前后

    引发了不可重复读

    不可重复读,一个事务读取到了另一个事务提交的数据,导致前后两次查询结果不一致.

    会造成问题是前后读取到的结果不一样,发生了不可重复读,就是不可以 重复读取, 就是不能执行多次读取, 否则会导致结果不一致, 这下好了, 读取已提交导致了 重复读取, 结果还不一致, 就出现了叫 不可重复读 现象.

    安全隐患_可重复读

    Repeatable Read重复读, 重复读就是mysql默认的隔离级别,可以让食物在自己的会话中重复读取数据,并且不会出现结果不一致的现象, 就算其他事务提交了, 也还是会在窗口中出现以前的数据, 这就是可重复读了.

    重复读, 就是让它可以重复查询, 结果还是和以前一样的效果出现.

    设置重复读

    重复读 重复读

    安全隐患 _可串行化

    幻读:什么是幻读呢?
    就是一个事务读到另一个事务已提交的插入的数据,会导致多次查询结果不一致.就是幻读,是不是幻读理解为我幻想了, 事务已提交的插入数据, 导致幻想了,(幻读) 导致每次查询结果不一样.

    事务已提交,多次查询结果不一致.

    幻读->Serializable可串行化

    该事务的级别是最高的事务级别,我是可串行化,是最高的.可以解决如下小弟的问题,如脏读,不可重复读,幻读,因为我是可串行化,是大佬,但作为大佬,还是会有缺点的.

    命令行 命令 命令

    是的,a提交才动.现在我们让b先开启事务.

    命令 命令行 提交了

    可串行化, 谁先打开事务,就谁有权利,这个隔离级别,先打开就有权利让别人等着,等先打开事务的那个家伙,提交或者回滚后,才能进行,这种级别是用得比较少的,因为容易导致性能上效率低下.

    隔离级别有四个哦

    1. 读未提交
    2. 读已提交
    3. 可重复读
    4. 可串行化

    如果按照效率划分,从高到低,排个名次如下:

    1. 读未提交 -> 脏读
    2. 读已提交 -> 不可重复读
    3. 可重复读 -> 解决重复读
    4. 可串行化 -> 以上都是我小弟来着

    按照拦截程度来划分,从高到底,排名如下:

    1. 可串行化 -> 我是大哥
    2. 可重复读 -> 我是二哥
    3. 读已提交 -> 我是三弟
    4. 读未提交 -> 我是小弟

    事务_隔离级别小结

    // 使用事务
    conn.setAutoCommit(false);
    // 提交
    conn.commit();
    // 回滚
    conn.rollback();
    

    事务只是针对连接对象.事务是会自动提交的.

    安全隐患和隔离级别

    安全隐患: 读的安全隐患和写的安全隐患

    读:
    脏读,读到未提交的数据,一个事务读到了另一个事务未提交的数据;
    不可重复读,就是一个事务读到了另一个事务已经提交的数据,导致前后两次查询的结果不一致;
    幻读,就是一个事务读到了另一个事务添加的数据,导致前后查询结果不一致.

    写: 丢失更新...

    隔离级别

    读未提交,导致脏读
    读已提交,解决脏读,导致不可重复读
    可重复读,解决脏读和不可重复读,导致幻读
    可串行化,解决脏读,不可重复读,幻读

    默认的mysql是可重复读,oracle默认是读已提交

    写的问题_丢失更新

    丢失更新

    1. 乐观锁
    2. 悲观锁

    安全问题包含 读的问题和写的问题

    事务的特性是什么?
    原子性,一致性,隔离性,持久性

    写的问题_丢失更新

    效果 效果

    b窗口没有提交.等待提交中:

    案例控制面板,我的a:

    a的 b的

    哭了,这是设置默认的重复读啊!

    丢失更新的问题

    听说丢失更新

    a事务和b事务同时查询一个表,a开始修改并提交name字段的名字,然后b事务开始修改该行的money的字段,如果b事务提交,那么之前a事务修改的名字没有了,变回去了哦,当然b事务回滚,也同样导致a事务更新没有了哦.回滚也会把之前b事务的最初的数据还原.

    这里的情况处理序列化级别外,就是可串行化级别大佬哦!

    解决丢失更新的方法

    1. 悲观锁
    2. 乐观锁
    select * from account;
    

    悲观锁的态度,它是悲观的态度,它是一定会丢失更新,它的想法是我一定会出错.

    而乐观锁,它的态度是我一定不会丢失更新.

    悲观锁

    数据库的锁机制,排他锁

    select * from account for update;
    
    命令 命令行

    丢失更新的问题

    不考虑隔离性,产生写入数据导致的问题为丢失更新的问题,两个事务同时对某一条记录做修改,然后会导致丢失更新的问题.

    a,b两个事务同时获取一条数据,同时做了修改,a事务修改后,提交了事务,b事务修改后,不管是提交还是回滚,都会对数据发生影响.

    悲观锁记住用了这句:

    select * from account for update;
    for update;
    数据库锁机制,排他锁
    

    乐观锁

    a事务先提交,数据库版本version变为1,b事务在提交的时候,比对数据库version和自己的version是不一样的,不允许提交,要先更新.

    a提交的时候版本变为1,b提交的时候,发现版本不一致就无法提交,要进行更新后提交.

    数据库连接池

    什么是连接池,连接池的作用是什么,自定义连接池,开源的连接池?

    那么什么是数据库连接池?

    数据库连接池是Java程序和数据连接的中介媒介,以前一个Java程序对应一个连接,然后就可以连接到数据了,可以一旦多了呢?

    就有人发明了数据库连接池,可以一下连接多个,但是是有限制的,一旦多了,就会扩容,额外增加3到5个,不会增幅太大,也有最大值的限制.

    数据库的连接对象 创建工作 比较消耗性能
    一开始在内存中会开辟一块空间, 用于是 这个数据库连接池的空间, 可以在池子里放置很多个连接对象, 数据库连接池里有很多个连接对象, 后面需要连接的话会直接从池子里面去, 就不用自己去创建连接了, 因为数据库的连接对象创建工作是比较耗时的, 使用完, 数据库连接池中的 连接对象 ,是要进行归还的, 确保连接对象可以循环连接使用.

    创建数据库的连接池

    // 简单使用数据库连接池
    package com.dashucoding.util;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    public class TestPool {
        
        @Test
        public void testPool() {
            Connection conn = null;
            PreparedStatement ps = null;
            MyDataSource dataSource = new MyDataSource();
            try {
        
                conn = dataSource.getConnection();
                
                String sql = "insert into account values (null, 'xilali', 10)";
                ps = conn.prepareStatement(sql);
                ps.executeUpdate();
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                try {
                    ps.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // 归还连接
                dataSource.addBack(conn);
            }
        }
    }
    
    结构

    自定义数据库连接池

    List <Connection> list = new ArrayList<Connection>();
    

    解决自定义数据库连接池问题

    因为多了一个addBack方法,要记住这个方法,且不能用面向接口编程.修改close方法,改成不是关闭而是归还连接对象.

    public class MyDataSource implements DataSource {
     // 创建连接池
    List<Connection> list = new ArrayList<Connection>();
     public MyDataSource(){
      for(int i = 0; i < 10; i++){
       Connection conn = JDBCUtil.getConn();
       list.add(conn);
      }
     }
     @Override
     public Connection getConnection() throws SQLException {
       if(list.size() == 0){
         for(int i=0; i<5; i++) {
          Connection conn = JDBCUtil.getConn();
           list.add(conn);
         }
        }
        Connection conn = list.remove(0);
         return conn;
      }
      // 用完后归还 
      public void addBack(Connection conn){
        list.add(conn);
      }
    }
    
    public class TestPool{
     @Test
      public void testPool(){
       Connection conn = null;
       PreparedStatement ps = null;
       MyDataSource dataSource = new MyDataSource();
      try {
       conn = dataSource.getConnection();
       String sql = "insert into account values(null, 'dashu', 10)";
       ps = conn.prepareStatement(sql);
       ps.executeUpdate();
     
       }catch(SQLException e){
        e.printStackTrace();
       }finally{
        try{
        ps.close();
        }catch(SQLException e){
         e.printStackTrace();
        }
        // 归还连接
        dataSource.addBack(conn);
       }
      }
    }
    

    如何扩展方法

    装饰者模式

    package com.dashucoding.test;
    
    public interface Waiter {
        void service();
    }
    
    package com.dashucoding.test;
    
    public class Waitress implements Waiter {
        @Override
        public void service() {
            System.out.println("在服务...");
        }
    }
    
    package com.dashucoding.test;
    
    public class MainTest {
        public static void main(String[] args) {
            Waiter waiter = new Waitress();
            waiter.service();
        }
    }
    

    装饰者模式:

    package com.dashucoding.test;
    
    public class WaitressWrap implements Waiter {
        
        Waiter watier = null;
        public WaitressWrap(Waiter watier) {
            this.watier = watier;
        }
    
        @Override
        public void service() {
            // TODO Auto-generated method stub
            System.out.println("微笑");
            watier.service();
        }
        
    }
    
    package com.dashucoding.test;
    
    public class MainTest {
        public static void main(String[] args) {
            /*Waiter waiter = new Waitress();
            waiter.service();*/
            WaitressWrap waitressWrap = new WaitressWrap(new Waitress());
            waitressWrap.service();
        }
    }
    

    分析

    Waiter -> service()
    
    Waitress -> service()
    
    WaitressWrap -> service()
    
    Waiter waiter;
    public Waitress Wrap(Waiter waiter){
     this.waiter = watier;
    }
    void service(){
     syso
     waiter.service();
    }
    

    装饰者模式

    结构 代码
    package com.dashucoding.util;
    
    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.SQLFeatureNotSupportedException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.logging.Logger;
    
    import javax.sql.DataSource;
    // 这是一个数据库连接池
    // 一开始 先往连接池放入10个连接
    public class MyDataSource implements DataSource{
        
        // 创建连接池
        List<Connection> list = new ArrayList<Connection>();
        public MyDataSource() {
            // 10个连接
            for(int i = 0; i < 10; i++) {
                Connection conn = JDBCUtil.getConn();
                list.add(conn);
            }
        }
        
        // 该连接池对外公布的获取连接的方法
        @Override
        public Connection getConnection() throws SQLException {
            // 来拿连接的时候,看看,池子里面有没有
            if(list.size() == 0) {
                for(int i = 0; i < 5; i++) {
                    Connection  conn = JDBCUtil.getConn();
                    list.add(conn);
                }
            }
            
            // TODO Auto-generated method stub
            // 那一个 给连接 如果有10个,0,1,2,3,->10 这样给
            // 确保给
            // 移除就给了嘛
            // remove(0) -> 移除第一个
            Connection conn = list.remove(0);
            // 把对象抛出去的时候,对这个对象进行包装
            
            Connection connection = new ConnectionWrap(conn,list);
            
            return connection;
        }
        
        // 用完后记得归还
        public void addBack(Connection conn) {
            list.add(conn);
        }
        
        
        
        
        
        
        
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            // TODO Auto-generated method stub
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter arg0) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setLoginTimeout(int arg0) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public boolean isWrapperFor(Class<?> arg0) throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public <T> T unwrap(Class<T> arg0) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
    
    
        @Override
        public Connection getConnection(String arg0, String arg1) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
    }
    
    代码
    package com.dashucoding.util;
    
    import java.sql.Array;
    import java.sql.Blob;
    import java.sql.CallableStatement;
    import java.sql.Clob;
    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.NClob;
    import java.sql.PreparedStatement;
    import java.sql.SQLClientInfoException;
    import java.sql.SQLException;
    import java.sql.SQLWarning;
    import java.sql.SQLXML;
    import java.sql.Savepoint;
    import java.sql.Statement;
    import java.sql.Struct;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.concurrent.Executor;
    
    public class ConnectionWrap implements Connection{
        
        Connection connection = null;
        
        List<Connection> list;
        public ConnectionWrap(Connection connection,List<Connection> list) {
            super();
            this.connection = connection;
            this.list = list;
        }
    
        @Override
        public void close() throws SQLException {
            // TODO Auto-generated method stub
            //connection.close();
            System.out.println("有人归还连接对象了,归还之前"+list.size());
            list.add(connection);
            System.out.println("有人归还连接对象了,归还之后"+list.size());
        }
        
        @Override
        public PreparedStatement prepareStatement(String sql) throws SQLException {
            // TODO Auto-generated method stub
            return connection.prepareStatement(sql);
        }
        
        
        
        
        
        
        
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void abort(Executor executor) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void clearWarnings() throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
    
    
        @Override
        public void commit() throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Blob createBlob() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Clob createClob() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public NClob createNClob() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public SQLXML createSQLXML() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Statement createStatement() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public boolean getAutoCommit() throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public String getCatalog() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Properties getClientInfo() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public String getClientInfo(String name) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public int getHoldability() throws SQLException {
            // TODO Auto-generated method stub
            return 0;
        }
    
        @Override
        public DatabaseMetaData getMetaData() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public int getNetworkTimeout() throws SQLException {
            // TODO Auto-generated method stub
            return 0;
        }
    
        @Override
        public String getSchema() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public int getTransactionIsolation() throws SQLException {
            // TODO Auto-generated method stub
            return 0;
        }
    
        @Override
        public Map<String, Class<?>> getTypeMap() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public SQLWarning getWarnings() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public boolean isClosed() throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public boolean isReadOnly() throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public boolean isValid(int timeout) throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public String nativeSQL(String sql) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public CallableStatement prepareCall(String sql) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
                int resultSetHoldability) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
    
    
        @Override
        public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
                int resultSetHoldability) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void releaseSavepoint(Savepoint savepoint) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void rollback() throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void rollback(Savepoint savepoint) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setAutoCommit(boolean autoCommit) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setCatalog(String catalog) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setClientInfo(Properties properties) throws SQLClientInfoException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setClientInfo(String name, String value) throws SQLClientInfoException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setHoldability(int holdability) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setReadOnly(boolean readOnly) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public Savepoint setSavepoint() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Savepoint setSavepoint(String name) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void setSchema(String schema) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setTransactionIsolation(int level) throws SQLException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
            // TODO Auto-generated method stub
            
        }
        
    }
    
    效果 代码

    数据库连接池_DBCP

    DBCP开源连接池
    C3P0,什么是C3P0,怎么用

    DBCP为数据库连接池,是java数据库连接池的一种是Apache开发的,通过数据库连接池可以让程序自动管理数据库的连接.

    DataBase Connection Pool数据库连接池
    

    C3P0也是一种开源的连接池,实现了数据库和JNDI绑定,使用它的开源项目:

    Spring, Hibernate
    

    怎么用DBCP

    1. 导入jar包
    commons-dbcp.jar
    commons-pool.jar
    
    // 不使用配置文件
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://loclhost/users");
    dataSource.setUsername("root");
    dataSource.setPassword("root");
    
    conn = dataSource.getConnection();
    String sql = "select * from user";
    pstmt = conn.prepareStatement(sql);
    

    DBCP连接数据库使用

    package com.dashucoding.dbcp;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    import org.apache.commons.dbcp.BasicDataSource;
    import org.junit.Test;
    
    import com.dashucoding.util.JDBCUtil;
    
    // 这个连接池要连接数据库, 账号,密码
    public class DBCPDemo {
        // ctrl + 2 f
        private Connection conn;
        private PreparedStatement ps;
    
        @Test
        public void testDBCP01(){
            // 数据库的连接池, 作用创建和连接
            
            try {
                // 构建数据源对象
                BasicDataSource dataSource = new BasicDataSource();
                // 连接什么数据库,用户名和密码
                dataSource.setDriverClassName("com.mysql.jdbc.Driver");
                dataSource.setUrl("jdbc:mysql://localhost/bank");
                dataSource.setUsername("你的账户");
                dataSource.setPassword("你的密码");
                
                // 得到连接对象
                conn = dataSource.getConnection();
                
                String sql = "insert into account values(null, ?, ?)";
                
                ps = conn.prepareStatement(sql);
                
                ps.setString(1, "dashucoding");
                ps.setInt(2, 10000);
                
                ps.executeUpdate();
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, ps);
            }
            
        }
    }
    

    以上是不使用配置文件的情况.

    DBCP使用配置文件方式

    结构 效果
    package com.dashucoding.dbcp;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp.BasicDataSource;
    import org.apache.commons.dbcp.BasicDataSourceFactory;
    import org.junit.Test;
    
    import com.dashucoding.util.JDBCUtil;
    
    public class DBCPDemo02 {
    
        @Test
        public void testDBCP02() {
            /*BasicDataSource dataSource = new BasicDataSource();
            dataSource.setConnectionProperties("dbcpconfig.properties");*/
    
            
            Connection conn = null;
            PreparedStatement ps = null;
    
            // 数据库的连接池, 作用创建和连接
            try {
                BasicDataSourceFactory factory = new BasicDataSourceFactory();
                Properties properties = new Properties();
                InputStream is = new FileInputStream("src//dbcpconfig.properties");
                properties.load(is);
                DataSource dataSource = factory.createDataSource(properties);
    
                // 得到连接对象
                conn = dataSource.getConnection();
    
                String sql = "insert into account values(null, ?, ?)";
    
                ps = conn.prepareStatement(sql);
    
                ps.setString(1, "liuliuliu");
                ps.setInt(2, 10000);
    
                ps.executeUpdate();
    
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                JDBCUtil.release(conn, ps);
            }
    
        }
    
    }
    

    数据库连接池_C3P0

    不使用配置方式

    拷贝jar c3p0...jar
    
     Just put the jar file [lib/c3p0-0.9.1.2.jar] in your application's effective CLASSPATH
    
    ComboPooledDataSource cpds = new ComboPooledDataSource();
    cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver            
    cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
    cpds.setUser("dbuser");                                  
    cpds.setPassword("dbpassword");   
    
    结构
    package com.dashucoding.c3p0;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    import org.apache.commons.dbcp.BasicDataSource;
    import org.junit.Test;
    
    import com.dashucoding.util.JDBCUtil;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class C3P0Demo {
        @Test
        public void testC3P0() {
    
            Connection conn = null;
            PreparedStatement ps = null;
            try {
                // 创建dataSource
                ComboPooledDataSource dataSource = new ComboPooledDataSource();
                
                dataSource.setDriverClass("com.mysql.jdbc.Driver");        
                dataSource.setJdbcUrl( "jdbc:mysql://localhost/bank" );
                dataSource.setUser("root");                                  
                dataSource.setPassword("admin");  
                
    
                // 得到连接对象
                conn = dataSource.getConnection();
    
                String sql = "insert into account values(null, ?, ?)";
    
                ps = conn.prepareStatement(sql);
    
                ps.setString(1, "aaa");
                ps.setInt(2, 10000);
    
                ps.executeUpdate();
    
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                JDBCUtil.release(conn, ps);
            }
    
        }
    
    }
    

    C3P0使用配置文件的方式

    图片 图片 效果

    c3p0-config.xml file:

    <?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/bank</property>
        <property name="user">你的账户</property>
        <property name="password">你的密码</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>
      
    </c3p0-config>
    
    效果
    package com.dashucoding.c3p0;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    
    import org.junit.Test;
    
    import com.dashucoding.util.JDBCUtil;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    // 使用配置文件
    public class C3P0Demo02 {
    
        @Test
        public void testC3P0() {
    
            Connection conn = null;
            PreparedStatement ps = null;
            try {
                // 配置文件 new了一个对象
                ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
                
                // 得到连接对象
                conn = dataSource.getConnection();
    
                String sql = "insert into account values(null, ?, ?)";
                ps = conn.prepareStatement(sql);
                ps.setString(1, "bbb");
                ps.setInt(2, 10000);
                ps.executeUpdate();
    
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                JDBCUtil.release(conn, ps);
            }
    
        }
    }
    

    可以弄oracle:

    <!-- This app is massive! -->
      <named-config name="oracle"> 
        <property name="acquireIncrement">50</property>
        <property name="initialPoolSize">100</property>
        <property name="minPoolSize">50</property>
        <property name="maxPoolSize">1000</property>
    
        <!-- intergalactoApp adopts a different approach to configuring statement caching -->
        <property name="maxStatements">0</property> 
        <property name="maxStatementsPerConnection">5</property>
    
        <!-- he's important, but there's only one of him -->
        <user-overrides user="master-of-the-universe"> 
          <property name="acquireIncrement">1</property>
          <property name="initialPoolSize">1</property>
          <property name="minPoolSize">1</property>
          <property name="maxPoolSize">5</property>
          <property name="maxStatementsPerConnection">50</property>
        </user-overrides>
      </named-config>
    

    oracle:

    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    

    DBUtils

    什么是DBUtils呢?怎么用呢?

    优化数据库连接,使用C3P0:

    package com.dashucoding.util;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class JDBCUtil02 {
        
        static ComboPooledDataSource dataSource = null;
    
        static {
            dataSource = new ComboPooledDataSource();
        }
        /**
         * 获取连接对象
         * @return
         * @throws SQLException 
         */
        public static Connection getConn() throws SQLException{
            
            return dataSource.getConnection();
        }
        
        /**
         * 释放资源
         * @param conn
         * @param st
         * @param rs
         */
        public static void release(Connection conn , Statement st , ResultSet rs){
            closeRs(rs);
            closeSt(st);
            closeConn(conn);
        }
        public static void release(Connection conn , Statement st){
            closeSt(st);
            closeConn(conn);
        }
    
        
        private static void closeRs(ResultSet rs){
            try {
                if(rs != null){
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                rs = null;
            }
        }
        
        private static void closeSt(Statement st){
            try {
                if(st != null){
                    st.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                st = null;
            }
        }
        
        private static void closeConn(Connection conn){
            try {
                if(conn != null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                conn = null;
            }
        }
    }
    

    DBUtils优化增删改查方法

    导包,两行代码交你增删改查,6666!

    QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
    queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
    

    两行.

    效果 效果
    package com.dashucoding.dbutils;
    
    import java.sql.SQLException;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.junit.Test;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class TestDBUtils {
        @Test
        public void testInsert() throws SQLException {
    //      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    
            // dbutils 简化了CRUD的代码
            QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
            
            /*
             * queryRunner.update(sql);
             * 增删改
             * queryRunner.query(sql, rsh);
             * 查
             * */
            
            queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
        }
    
    }
    
    package com.dashucoding.dbutils;
    
    import java.sql.SQLException;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.junit.Test;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class TestDBUtils {
        @Test
        public void testInsert() throws SQLException {
    //      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    
            // dbutils 简化了CRUD的代码
            QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
            
            /*
             * queryRunner.update(sql);
             * 增删改
             * queryRunner.query(sql, rsh);
             * 查
             * */
            
            queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
            queryRunner.update("delete from account where id = ?", 8);
            queryRunner.update("update account set money = ? where id = ?", 0, 10);
        }
    
    }
    

    查询

    效果
    package com.dashucoding.dbutils;
    
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.ResultSetHandler;
    import org.junit.Test;
    
    import com.dashucoding.domain.Account;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class TestDBUtils {
        @Test
        public void testInsert() throws SQLException {
    //      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    
            // dbutils 简化了CRUD的代码
            QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
            // 查询的是一个Bean对象
            // new 匿名实现类->new接口的匿名实现类
            
            Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>() {
                // 去执行查询,查询到的数据在result里面,然后调用handle方法,用户手动去封装
                @Override
                public Account handle(ResultSet rs) throws SQLException {
                    // TODO Auto-generated method stub
                    Account account = new Account();
                    
                    while(rs.next()) {
                        String name = rs.getString("name");
                        int money = rs.getInt("money");
                        account.setName(name);
                        account.setMoney(money);
                    }
                    return account;
                }
                
            }, 1);
            System.out.println(account.toString());
            
            /*
             * queryRunner.update(sql);
             * 增删改
             * queryRunner.query(sql, rsh);
             * 查
             * */
            
            /*queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
            queryRunner.update("delete from account where id = ?", 8);
            queryRunner.update("update account set money = ? where id = ?", 0, 10);*/
        }
    
    }
    

    查询优化

    效果

    一个对象: BeanHandler<T>

    一个集合里面有很多对象: BeanListHandler<T>

    package com.dashucoding.domain;
    
    public class Account {
        private String name;
        private int money;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getMoney() {
            return money;
        }
        public void setMoney(int money) {
            this.money = money;
        }
        @Override
        public String toString() {
            return "Account [name=" + name + ", money=" + money + "]";
        }
        
    }
    
    package com.dashucoding.dbutils;
    
    import java.sql.SQLException;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.ResultSetHandler;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.junit.Test;
    
    import com.dashucoding.domain.Account;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class TestDBUtils {
        @Test
        public void testInsert() throws SQLException {
    //      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    
            // dbutils 简化了CRUD的代码
            QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
            // 查询的是一个Bean对象
            // new 匿名实现类->new接口的匿名实现类
            
            /*Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>() {
                // 去执行查询,查询到的数据在result里面,然后调用handle方法,用户手动去封装
                @Override
                public Account handle(ResultSet rs) throws SQLException {
                    // TODO Auto-generated method stub
                    Account account = new Account();
                    
                    while(rs.next()) {
                        String name = rs.getString("name");
                        int money = rs.getInt("money");
                        account.setName(name);
                        account.setMoney(money);
                    }
                    return account;
                }
                
            }, 1);
            System.out.println(account.toString());*/
            
            // 接口的实现类-> ResultSetHandler的实现类
            // Ctrl + t 实现类
            //ResultSetHandler
            
            // 一个对象查询一个对象使用BeanHandler
            Account account = queryRunner.query("select * from account where id = ?", new BeanHandler<Account>(Account.class), 1);
            System.out.println(account.toString());
            /*
             * queryRunner.update(sql);
             * 增删改
             * queryRunner.query(sql, rsh);
             * 查
             * */
            
            /*queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
            queryRunner.update("delete from account where id = ?", 8);
            queryRunner.update("update account set money = ? where id = ?", 0, 10);*/
        }
    
    }
    

    优化成两行代码:

    贴图
    Account account = queryRunner.query("select * from account where id = ?", new BeanHandler<Account>(Account.class), 1);
    System.out.println(account.toString());
    

    查询多个数据

    效果
    // 查询多个对象
    List<Account> list = queryRunner.query("select * from account",
                    new BeanListHandler<Account>(Account.class));
    for(Account account : list) {
     System.out.println(account.toString());
    }
    
    package com.dashucoding.dbutils;
    
    import java.sql.SQLException;
    import java.util.List;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.ResultSetHandler;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import org.junit.Test;
    
    import com.dashucoding.domain.Account;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class TestDBUtils {
        @Test
        public void testInsert() throws SQLException {
    //      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    
            // dbutils 简化了CRUD的代码
            QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
            // 查询的是一个Bean对象
            // new 匿名实现类->new接口的匿名实现类
            
            /*Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>() {
                // 去执行查询,查询到的数据在result里面,然后调用handle方法,用户手动去封装
                @Override
                public Account handle(ResultSet rs) throws SQLException {
                    // TODO Auto-generated method stub
                    Account account = new Account();
                    
                    while(rs.next()) {
                        String name = rs.getString("name");
                        int money = rs.getInt("money");
                        account.setName(name);
                        account.setMoney(money);
                    }
                    return account;
                }
                
            }, 1);
            System.out.println(account.toString());*/
            
            // 接口的实现类-> ResultSetHandler的实现类
            // Ctrl + t 实现类
            //ResultSetHandler
            
            // 一个对象查询一个对象使用BeanHandler
            /*Account account = queryRunner.query("select * from account where id = ?",
                    new BeanHandler<Account>(Account.class), 1);
            System.out.println(account.toString());*/
            
            /*List<Account> account = queryRunner.query("select * from account",
                    new BeanListHandler<Account>(Account.class));*/
            // 查询多个对象
            List<Account> list = queryRunner.query("select * from account",
                    new BeanListHandler<Account>(Account.class));
            for(Account account : list) {
                System.out.println(account.toString());
            }
            
            /*
             * queryRunner.update(sql);
             * 增删改
             * queryRunner.query(sql, rsh);
             * 查
             * */
            
            /*queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
            queryRunner.update("delete from account where id = ?", 8);
            queryRunner.update("update account set money = ? where id = ?", 0, 10);*/
        }
    
    }
    

    小结

    // 通过类的字节码,获得该类的实例:
    Account a = new Account();
    
    Account a1 = Account.class.newInstance();
    
    new BeanHandler<Account>(Account.class)
    
    new BeanListHandler<Account>(Account.class)
    
    小结

    ResultSetHandler<T>

    实现类:

    贴图

    总结

    事务,连接池,DBUtils

    查询:

    贴图
    QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
    
    queryRunner.update();
    queryRunner.query
    
    1. 事务
      脏读
      不可重复读
      幻读

    丢失更新 写的问题
    悲观锁 for update
    乐观锁 ,添加字段版本级别

    4个隔离级别
    读未提交
    读已提交
    可重复读
    可串行化

    读未提交,引发脏读
    读已提交,引发不可重复读,解决了脏读

    可重复读,引发了幻读,解决了脏读,不可重复读
    可串行化(序列化),解决了脏读,不可重复读,幻读,引发效率低下问题

    数据库连接池

    1. BCP -> 不使用配置 使用配置
    2. C3P0 -> 不使用配置 使用配置
    3. 自定义连接池 -> 饰者模式

    结言

    可在评论发表你的总结内容,做功课哦!

    如果看了觉得不错

    点赞!转发!

    达叔小生:往后余生,唯独有你
    You and me, we are family !
    90后帅气小伙,良好的开发习惯;独立思考的能力;主动并且善于沟通
    简书博客: 达叔小生
    https://www.jianshu.com/u/c785ece603d1

    结语

    • 下面我将继续对 其他知识 深入讲解 ,有兴趣可以继续关注
    • 小礼物走一走 or 点赞

    相关文章

      网友评论

        本文标题:第77节:Java中的事务和数据库连接池和DBUtiles

        本文链接:https://www.haomeiwen.com/subject/masvjqtx.html