JDBC 事务控制

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

  2. 操作:

    • 开启事务:mysql----->start transaction
    • 提交事务:commit
    • 回滚事务:rollback
  3. 使用Connection对象来管理事务

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

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

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

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

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

    // 含有事务的转账
    public static void transform02() {
    // 让张三给李四转账10000钱
    /*
    * 首先让张三的钱减少10000
    * 然后让李四的钱增加10000
    */
    //定义实现转账的两条sql语句
    double money = 10000;
    String username01 = "张三";
    String username02= "李四"; String sql01 = "update account set balance = balance-? where username = ?";
    String sql02 = "update account set balance = balance+? where username = ?";
    // 使用Connection对象手动开启事务 setAutoCommit(boolean autoCommit):
    Connection con = DBUtil.getConnection();
    try {
    con.setAutoCommit(false);
    // 通过con获取预处理对象 先让张三的钱减少10000
    ps01 = con.prepareStatement(sql01);
    ps01.setDouble(1, money);
    ps01.setString(2, username01);
    // 执行sql语句
    int count = ps01.executeUpdate();
    // 手动制造一个异常
    int i = 1 / 0;
    // 再让李四的钱增加10000
    // 通过con获取预处理对象
    ps02 = con.prepareStatement(sql02);
    ps02.setDouble(1, money);
    ps02.setString(2, username02);
    // 执行sql语句
    int coun02 = ps02.executeUpdate();
    // 提交事务
    con.commit();
    System.out.println("转账成功!");
    } catch (Exception e) {
    // 事务回滚
    try {
    con.rollback();
    System.out.println("转账失败!");
    } catch (SQLException e1) {
    e1.printStackTrace();
    }
    e.printStackTrace();
    }finally {
    // 把打开的各种连接对象释放掉
    try {
    ps02.close();
    ps01.close();
    con.close();
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }
    }

连接池

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

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

  2. 好处:

    • 可以大大节省系统开销
    • 可以提高访问的速度。

  1. 实现操作:

    ​ javax.sql 连接池

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

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

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

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

    1. c3p0: 它是数据库连接池的一套技术
    2. druid:也是一套数据据库连接池的技术,由阿里巴巴提供的。
  2. 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()
  3. 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
        }

jdbc事务、连接池概念、c3p0、Driud、JDBC Template、DBUtils的更多相关文章

  1. day18(JDBC事务&连接池介绍&DBUtils工具介绍&BaseServlet作用)

    day18总结 今日思维导图: 今日内容 事务 连接池 ThreadLocal BaseServlet自定义Servlet父类(只要求会用,不要求会写) DBUtils à commons-dbuti ...

  2. JDBC数据源连接池(2)---C3P0

    我们接着<JDBC数据源连接池(1)---DBCP>继续介绍数据源连接池. 首先,在Web项目的WebContent--->WEB-INF--->lib文件夹中添加C3P0的j ...

  3. java mysql多次事务 模拟依据汇率转账,并存储转账信息 分层完成 dao层 service 层 client层 连接池使用C3p0 写入库使用DBUtils

    Jar包使用,及层的划分 c3p0-config.xml <?xml version="1.0" encoding="UTF-8"?> <c3 ...

  4. JDBC数据源连接池(3)---Tomcat集成DBCP

    此文续<JDBC数据源连接池(2)---C3P0>. Apache Tomcat作为一款JavaWeb服务器,内置了DBCP数据源连接池.在使用中,只要进行相应配置即可. 首先,确保Web ...

  5. c3p0、dbcp、tomcat jdbc pool 连接池配置简介及常用数据库的driverClass和驱动包

    [-] DBCP连接池配置 dbcp jar包 c3p0连接池配置 c3p0 jar包 jdbc-pool连接池配置 jdbc-pool jar包 常用数据库的driverClass和jdbcUrl ...

  6. DBCP,C3P0与Tomcat jdbc pool 连接池的比较

    hibernate开发组推荐使用c3p0; spring开发组推荐使用dbcp(dbcp连接池有weblogic连接池同样的问题,就是强行关闭连接或数据库重启后,无法reconnect,告诉连接被重置 ...

  7. JDBC数据源连接池(1)---DBCP

    何为数据源呢?也就是数据的来源.我在前面的一篇文章<JDBC原生数据库连接>中,采用了mysql数据库,数据来源于mysql,那么mysql就是一种数据源.在实际工作中,除了mysql,往 ...

  8. JDBC之 连接池

    JDBC之 连接池 有这样的一种现象: 用java代码操作数据库,需要数据库连接对象,一个用户至少要用到一个连接.现在假设有成千上百万个用户,就要创建十分巨大数量的连接对象,这会使数据库承受极大的压力 ...

  9. JDBC数据源连接池(4)---自定义数据源连接池

    [续上文<JDBC数据源连接池(3)---Tomcat集成DBCP>] 我们已经 了解了DBCP,C3P0,以及Tomcat内置的数据源连接池,那么,这些数据源连接池是如何实现的呢?为了究 ...

  10. jdbc数据连接池dbcp要导入的jar包

    jdbc数据连接池dbcp要导入的jar包 只用导入commons-dbcp-x.y.z.jarcommons-pool-a.b.jar

随机推荐

  1. MySQL-索引分类及使用索引

    1.什么是索引? 索引:存储引擎用于快速找到记录的一种数据结构,默认使用B-Tree索引.索引是存储引擎层中实现.简单理解为:排好序的快速查找数据结构 索引的目的:提高数据查询的效率,优化查询性能,就 ...

  2. web移动端点击穿透问题

    在移动端开发的时候,我们有时候会遇到这样一个bug:点击关闭遮罩层的时候,遮罩层下面的带有点击的元素也会被触发,给人一种击穿了页面的感觉,这是为什么呢?主要是因为用户touch事件关闭按钮的时候,触发 ...

  3. Python搭建调用本地dll的Windows服务(浏览器可以访问,附测试dll64位和32位文件)

    一.前言说明 博客声明:此文链接地址https://www.cnblogs.com/Vrapile/p/14113683.html,请尊重原创,未经允许禁止转载!!! 1. 功能简述 (1)本文提供生 ...

  4. Windows10自带截屏快捷键

    Windows10自带截屏快捷键使用方法大全我们知道,QQ和微信以及第三方浏览器等软件都支持截图功能,但是这个都是基于软件的一个功能,如果我们不打开这些软件的话,就不能实现截图功能,但其实window ...

  5. 最简单的 K8S 部署文件编写姿势,没有之一!

    1. 头疼编写K8S部署文件? K8S yaml 参数很多,需要边写边查? 保留回滚版本数怎么设? 如何探测启动成功,如何探活? 如何分配和限制资源? 如何设置时区?否则打印日志是GMT标准时间 如何 ...

  6. AWT01-体系概述

    1.概述 AWT(Abstract Window Toolkit),中文译为抽象窗口工具包,该包提供了一套与本地图形界面进行交互的接口,是Java提供的用来建立和设置Java的图形用户界面的基本工具. ...

  7. 如何自定义Kubernetes资源

    目前最流行的微服务架构非Springboot+Kubernetes+Istio莫属, 然而随着越来越多的微服务被拆分出来, 不但Deploy过程boilerplate的配置越来越多, 且繁琐易错, 维 ...

  8. 第一篇:docker 简单入门(一)

    本篇目录 写在最前面的话 docker概念介绍 镜像的概念.容器的概念 docker的安装介绍 写在最前面的话 由于此类文章博客园鉴定为简单文章,所以已经移到csdn[https://blog.csd ...

  9. SpringBoot进阶教程(六十七)RateLimiter限流

    在上一篇文章nginx限流配置中,我们介绍了如何使用nginx限流,这篇文章介绍另外一种限流方式---RateLimiter. v限流背景 在早期的计算机领域,限流技术(time limiting)被 ...

  10. vue API 知识点(3) --- 实例 总结

    一.实例 property 1.vm.$data Vue 实例观察的数据对象,Vue 实例代理了对其 data 对象 property 的的访问 2.vm.$props 当前组件接收到的 props ...