• 04_ThreadLocal整合事务操作


    文章导读:

    本文主要讲解了如何在没有框架情况下如何解决Dao的事务问题, 重点理解Connection存放到WeakReference中为什么垃圾回收的时候Connection不回收

    视频与源码下载:http://edu.51cto.com/lecturer/index/user_id-9166337.html  (代码在视频的附件中)

    先准备下测试的环境:db.sql、model、dao、Service

    db.sql 代码如下(只有一张表)

     1 /*删除商城数据库,如果存在*/
     2 drop database if exists demo;
     3 create database demo default character set utf8;
     4 use demo;
     5 drop table if exists book;
     6 
     7 create table book
     8 (
     9    id                  int not null auto_increment,
    10    name                varchar(20),
    11    price               decimal(8,2),
    12    remark              longtext,
    13    storage             int,
    14    primary key (id)
    15 );
    16 
    17 /* 图书测试用例 */
    18 insert into book (name,price,remark,storage) values ('Java编程思想',99.99,'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉',200);
    19 insert into book (name,price,remark,storage) values ('HTML5与CSS3权威指南',49.99,'一本前端应用开发的书籍',300);
    20 insert into book (name,price,remark,storage) values ('Android从入门到精通',79.99,'移动互联网书籍',100);
    21 
    22 select * from book;

    执行SQL语句结果如下:

    根据表生成Java的model(模型)

     1 public class Book {
     2 
     3     private Integer id;
     4     private String name;
     5     private Double price;
     6     private String remark;
     7     public Integer storage;
     8 
     9           // ..... 省略了 set get方法
    10 }

    编写一个BookDaoImpl完成数据的插入功能

     1 public class BookDaoImpl {
     2 
     3     public int save(Book book) {
     4         String sql = "insert into book (name,price,remark,storage) values (?,?,?,?)";
     5         Connection conn = null;
     6         PreparedStatement pre = null;
     7         try {
     8             conn = JdbcUtils.getConnection();
     9             System.out.println("BookDaoImpl conn:" + conn);
    10             pre = conn.prepareStatement(sql);
    11             pre.setString(1, book.getName());
    12             pre.setDouble(2, book.getPrice());
    13             pre.setString(3, book.getRemark());
    14             pre.setInt(4, book.getStorage());
    15             return pre.executeUpdate();
    16         } catch (SQLException e) {
    17             throw new RuntimeException(e);
    18         } finally {
    19             try {
    20                 pre.close();
    21             } catch (SQLException e) {
    22                 throw new RuntimeException(e);
    23             } 
    24         }
    25     }
    26 }

    编写一个AuthorDaoImpl完成作者插入功能(主要是为了测试事务, 如果两个方法有一个方法执行失败,则事务要回滚)

    public class AuthorDaoImpl {
    
        public int save() {
            Connection conn = JdbcUtils.getConnection();
            System.out.println("AuthorDaoImpl conn:" + conn);
            System.out.println("----另一张表插入作者信息-----");
    //        Integer.parseInt("xxxx");
            return 0;
        }
    }

    最后编写一个Service把需要的事务操作整合起来, Conn的创建与销毁都在Service中.

     1 public class BookServiceImpl {
     2     
     3     private BookDaoImpl bookDaoImpl = new BookDaoImpl();
     4     private AuthorDaoImpl authorDaoImpl = new AuthorDaoImpl();
     5     
     6     public static void main(String[] args) {
     7         BookServiceImpl serviceImpl=new BookServiceImpl();
     8         serviceImpl.save();
     9         System.out.println("---------------------over------------------------");
    10     }
    11     
    12     // 业务逻辑完成之后调用数据访问层,来实现数据入库
    13     public void save(){
    14         Connection conn = null;
    15         try{
    16             conn = JdbcUtils.getConnection();
    17             // 手动提交事务
    18             conn.setAutoCommit(false);
    19             // 事务应该在业务逻辑层创建,包含所有事务的dao
    20             bookDaoImpl.save(new Book(null, "测试书籍", 45.67, "我是备注", 100));
    21             System.gc(); // 手动调用垃圾回收并不会导致弱引用Connection关闭,因为当前处于Open状态
    22             authorDaoImpl.save();
    23             conn.commit();
    24         }catch (Exception e) {
    25             try {
    26                 System.out.println("conn.rollback()");
    27                 conn.rollback();
    28             } catch (SQLException e1) {
    29                 throw new RuntimeException(e1);
    30             }
    31             throw new RuntimeException(e);
    32         }finally{
    33             JdbcUtils.closeConnection(); // 必须要关闭,否则不会被销毁.因为Connecion默认是open状态
    34         }
    35     }
    36 }

    测试结果如下(通过测试我们会发现,两个Dao中使用的是同一个事务,如果出错事务将会回滚,在测试的时候会发现如果调用的gc也不会导致弱引用的Connection回收, 为什么呢,因为Connection是Open状态,只要没有关闭是不会被回收的,理解相信的原理可以参考当前文章的视频教程)

  • 相关阅读:
    css 中 overflow: hidden清楚浮动的真正原因
    Get、Post请求中文乱码问题有效解决方法
    安装PostgreSQL和卸载PostgreSQL
    PostgresSql日期字段比较大小
    关于多线程编程的一点思考
    Python 虚拟环境 pyenv、venv(pyvenv)、virtualenv之间的区别
    python常用命令
    python中各种文件打开模式a w r
    python-安装
    day1-安装配置
  • 原文地址:https://www.cnblogs.com/jxyedu/p/6262778.html
Copyright © 2020-2023  润新知