• JDBC事务和连接池


    JDBC 事务控制

    1. 什么是事务:一个包含多个步骤或者业务操作。如果这个业务或者多个步骤被事务管理,则这多个步骤要么同时成功,要么回滚(多个步骤同时执行失败),这多个步骤是一个整体,不可分割的。

    2. 操作:

      • 开启事务:mysql----->start transaction

      • 提交事务:commit

      • 回滚事务:rollback

    3. 使用Connection对象来管理事务

      • 开启事务: setAutoCommit(boolean autoCommit): 指定该方法里面传入false值,手动开启事务。

        在执行sql语句之前开启事务。

      • 提交事务:commit();---->当所有的sql语句执行完毕才提交事务

      • 回滚事务:rollback();---->当事务中发生异常时回滚事务 回滚事务放在catch语句。

    4. 示例:以银行转账为例:让张三给李四转账10000钱

     1 // 含有事务的转账
     2     public static void transform02() {
     3         // 让张三给李四转账10000钱
     4         /*
     5          * 首先让张三的钱减少10000
     6          * 然后让李四的钱增加10000
     7          */
     8         //定义实现转账的两条sql语句
     9         double money = 10000;
    10         String username01 = "张三";
    11         String username02= "李四";
    12         
    13         String sql01 = "update account set balance = balance-? where username = ?";
    14         String sql02 = "update account set balance = balance+? where username = ?";
    15         // 使用Connection对象手动开启事务 setAutoCommit(boolean autoCommit):
    16         Connection con = DBUtil.getConnection();
    17         try {
    18             con.setAutoCommit(false);
    19             // 通过con获取预处理对象 先让张三的钱减少10000
    20             ps01 = con.prepareStatement(sql01);
    21             ps01.setDouble(1, money);
    22             ps01.setString(2, username01);
    23             // 执行sql语句
    24             int count = ps01.executeUpdate();
    25             // 手动制造一个异常
    26             int i = 1 / 0;
    27             // 再让李四的钱增加10000
    28             // 通过con获取预处理对象
    29             ps02 = con.prepareStatement(sql02);
    30             ps02.setDouble(1, money);
    31             ps02.setString(2, username02);
    32             // 执行sql语句
    33             int coun02 = ps02.executeUpdate();
    34             // 提交事务
    35             con.commit();
    36             System.out.println("转账成功!");
    37         } catch (Exception e) {
    38             // 事务回滚
    39             try {
    40                 con.rollback();
    41                 System.out.println("转账失败!");
    42             } catch (SQLException e1) {
    43                 e1.printStackTrace();
    44             }
    45             e.printStackTrace();
    46         }finally {
    47             // 把打开的各种连接对象释放掉
    48             try {
    49                 ps02.close();
    50                 ps01.close();
    51                 con.close();
    52             } catch (SQLException e) {
    53                 e.printStackTrace();
    54             }
    55         }
    56     }

    连接池

    1. 什么连接池:其实就是一个容器,在这个容器当中存放着多个连接对象。

      当系统开始运行时,可以让系统提前创建多个连接对象,放到容器中(连接池),当客户端需要连接对象时,可以从连接池中申请一个连接,去访问数据库,当该连接使用完毕时,不再释放归还给系统,而是把这个连接对象归还给连接池。

    2. 好处:

      • 可以大大节省系统开销

      • 可以提高访问的速度。

    数据库连接池操作

     

        3.实现操作:

        javax.sql 连接池

        JNDI -----> Java Naming and Directory Interface Java命名和目录接口

        使用JNDI 降低程序和数据库的耦合度,使你的程序更加方便配置和维护以及部署。

        是JavaEE中规范中的重要规范之一。是EJB的相关的知识。

        DataSource接口 它里面并不提供具体的实现,而是由驱动程序供应商(数据库厂商)提供

      1. c3p0: 它是数据库连接池的一套技术

      2. druid:也是一套数据据库连接池的技术,由阿里巴巴提供的。

      4.C3p0:数据库连接池技术

      步骤:

      • 去官网下载两个jar包:c3p0-0.9.5.2.jar 和 mchange-commons-java-0.2.12.jar

      • 植入到工程的classpath类路径下,不要忘记导入mysql驱动jar包 mysql-connector-java.jar

      • 定义配置文件:

        • 文件类型:c3p0.properties 或者 c3p0-config.xml

        • 路径:放到classpath类路径下 对于工程来说直接放到src下面即可

      • 获取DataSource对象 : 数据库连接池对象 通过实例化ComboPooledDataSource来获取

      • 从连接池中获取连接对象。 getConnection()

      5.Druid 德鲁伊连接池技术

      • 步骤:

        1. 去官网去下载一个德鲁伊的jar ---> druid-1.0.9.jar

        2. 定义配置文件:使用properties文件类型的,名字随便起

        3. 手动加载配置文件信息: Properties集合

        4. 获取DataSource对象 :通过工厂方式来实现的,DruidDataSourceFactory

        5. 从连接池中获取连接对象:getConnection()

    JDBC Template

    • Spring框架提供了对JDBC操作的简单封装,使用JDBCTemplate对象来简化JDBC开发流程。

    • 步骤:

      • 从官网下载对应的spring-jdbc相关的jar包,导入工程类路径下,放到lib文件夹下面即可

      • 创建JDBCTemplate对象。依赖于DataSouce连接池(数据源)

      • 使用JDBCTemplate对象中的api方法实现crud操作

        • DML操作: update()

        • DQL操作: 查询 不用select,使用query

          • query(): 将查询的结果集封装成JavaBean对象

            • query()方法的参数:RowMapper

              • 手动装配:使用匿名内部类,自定义装配查询的每条记录值

              • 自动装配:使用Spring提供的BeanPropertyRowMapper实现类,完成对数据的自动装配

                具体操作-->new BeanPropertyRowMapper<类型>(类型.class)

          • queryForMap(): 将查询的结果集封装成map集合,只能封装一条记录:键key是字段名,值value是字段值,结果集记录数只能是1

          • queryForList():将结果集封装成List集合,在list集合中有多条记录,每一条记录都是一个map集合

            List<Map<Object,Object>> list ;

          • queryFoObject():将结果集封装成一个对象,一般用于聚合函数 查询总记录数 int count()

        • 具体操作:

    // 增删改动作
       // 修改数据
        public static void modifyData() {
            
            int count = jdbcTemplate.update("update account set username = ? where username = ?", "小五","王五");
            System.out.println(count);
        }
        // 删除数据
        public static void deleteData() {
            int count = jdbcTemplate.update("delete from account where username = ?", "小五");
            System.out.println(count);
        }
        // 插入一条数据
        public static void insertDate() {
            int count = jdbcTemplate.update("insert into account values(null,?,?)", "王五",5000);
            System.out.println(count);
        }
        public static void test() {
            // 查询张三的这条信息 封装到账户对象中
            String username = "张三";
            String sql = "select * from account where username = ?";    
            Map<String, Object> map = jdbcTemplate.queryForMap(sql,username);
            System.out.println(map);// {id=1, username=张三, balance=20000.0}
        }
        
        // 简化手动封装的方法
        public static void queryAll() {
            String sql = "select * from account";
            // Incorrect column count: expected 1, actual 3
            List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
            System.out.println(list);
            
        }
        
        // 使用query方法优化queryBean方法
        public static void queryBean2() {
            List<Account> list = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
            System.out.println(list);
            
        }
        
        // 将查询到结果集封装成JavaBean对象
        public static void queryBean() {
            String sql = "select * from account where username = '张三'";
            // RowMapper<T>
            List<Account> list = jdbcTemplate.query(sql, new RowMapper<Account>() {
                @Override
                public Account mapRow(ResultSet set, int arg1) throws SQLException {
                    // 封装查询到每一条记录值
                    Account account = new Account();
                    int id = set.getInt(1);
                    String username = set.getString(2);
                    double balance = set.getDouble(3);
                    account.setId(id);
                    account.setUsername(username);
                    account.setBalance(balance);
                    return account;
                }
            });
            
            System.out.println(list);// [Account [id=1, username=张三, balance=20000.0]]
        }
        
        // 查询总记录   查询account表中的所有记录数
        public static void queryTotalNum() {
            // queryFoObject()
            Integer count = jdbcTemplate.queryForObject("select count(*) from account", Integer.class);
            System.out.println(count);// 4
        }
  • 相关阅读:
    用两个栈实现队列
    重建二叉树
    从尾到头打印链表
    替换空格
    字符串比较
    二维数组的查找
    ORACLE---Unit01: 数据库原理 、 SQL(DDL、DML)
    [Python]小甲鱼Python视频第035课(图形用户界面入门:EasyGui)课后题及参考解答
    [Python]小甲鱼Python视频第032课(异常处理:你不可能总是对的)课后题及参考解答
    [Python]小甲鱼Python视频第030课(文件系统:介绍一个高大上的东西)课后题及参考解答
  • 原文地址:https://www.cnblogs.com/lk625/p/14249023.html
Copyright © 2020-2023  润新知