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状态,只要没有关闭是不会被回收的,理解相信的原理可以参考当前文章的视频教程)

posted @ 2017-01-10 08:29  Java、Android企培  阅读(219)  评论(0编辑  收藏  举报