码迷,mamicode.com
首页 > 数据库 > 详细

由浅到深学习JDBC三

时间:2017-05-04 00:10:44      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:jdbc   threadlocal   jdbcutil   依赖注入   深入浅出   


JDBC6.0最终版。

数据访问层Dao

业务逻辑层service

我们在Dao层中封装了对表的常用操作,增删改查。

我们在Util里封装了JDBCUtil工具类解决冗余问题。

现在我们有一个银行转账问题:

1.根据卡号,密码,先查询

2.转出账户再余额足够的情况下,减去转出资金。

3转入账户添加转入资金。

对于2,3步骤我们因当把他们看作是一个事务,事务的原子性,一致性,隔离性。要求

要么一起成功,要么一起不成功。当然从现实考虑,也确实应当这样,如果在2,3步骤之间失败了

就回退。

这整个转账逻辑,我们可以称之为业务。所以针对软件的三层结构。我们把这部分称为-----业务层(service)


在service层调用Dao层的方法。

而在service层里的连接对象和Dao层里的连接对象不是同一个对象,这就会造成混乱,打破事务的一致性。

从而导致,转出钱减去了,转入账户没加钱。


Service方法中的事务控制失败。

原因:service控制事务时过的conn和DAO访问数据库使用的conn时两个不同对象

解决:

     保证service和Dao使用同一个conn对象

     1:通过参数传递。

     2:每个线程对象有一个Map属性,可以存储数据

     在service获得conn,将conn放入当前Thread对象,在DAO访问数据库时取时,从Thread取出conn

     ThreadLocal简介及使用:

          操作当前线程对象中的一小块空间。

          1创建ThreadLocal对象 ThreadLocal<Connection> tdl = new ThreadLocal<Connection>();

          2tdl.set(conn);将conn添加到当前线程。

          3tdl.get();获得当前线程中的数据

          4tdl.remove()移除当前线程里的数据

     

话不多说我们来看代码有三个文件 JDBC_Util3.java JDBC_Dao3.java JDBC_Service.java

JDBC_Util3.java

public class JDBC_Util3 {

       private static final Properties prop = new Properties();

       private static final ThreadLocal<Connection> tdl = new ThreadLocal<Connection>();

       

       static{

             InputStream is = null;

             try {

                    is = JDBC_Util3.class.getResourceAsStream("jdbc.properties");

                    prop.load(is);

                    String driverName = prop.getProperty("driverName");

                    Class.forName(driverName);

             } catch (Exception e) {

                    e.printStackTrace();

             }

             

       }

       //返回链接

       public static Connection getConnection() throws Exception {

             Connection conn = null;

             conn = tdl.get();//获得当前线程连接

             if(conn == null){

                    //说明当前线程没有conn

                    String user = prop.getProperty("user");

                    String password = prop.getProperty("password");

                    String url = prop.getProperty("url");

                    conn = DriverManager.getConnection(url,user,password);

                    //将当 conn存入线程

                    tdl.set(conn);

             }

             return conn;

       }

       /**

        * 释放资源

        */

       public static void release(ResultSet rs,Statement stm,Connection conn){

             try {

                    if(rs!=null){rs.close();}

                    if(stm!=null){stm.close();}

                    if(conn!=null){

                           conn.close();

                           tdl.remove();//移除当前线程对象中的conn

                           }

             } catch (SQLException e) {

                    e.printStackTrace();

             }

       }

}

JDBC_Dao3.java

public class JDBC_Dao3 {

       / /更新账户

       public void upDateAccount(Account toAcc) {

             Connection conn = null;

             PreparedStatement pstm = null;

             try {

                    conn = JDBC_Util3.getConnection();

                    String sql = "update account set card_id=?,"

                                 + "password=?,balance=?,phone=? where card_id=?";

                    pstm = conn.prepareStatement(sql);

                    pstm.setString(1, toAcc.getCardId());

                    pstm.setString(2, toAcc.getPassword());

                    pstm.setDouble(3, toAcc.getBalance());

                    pstm.setString(4, toAcc.getPhone());

                    pstm.setString(5, toAcc.getCardId());

                    int i  = pstm.executeUpdate();

             } catch (Exception e) {

                    e.printStackTrace();

             }finally{

                    JDBC_Util.release(null, pstm, null);

             }

       }

        // 查询账户

       public Account queryAccount(Integer toCardId) {

             Connection conn = null;

             Statement stm = null;

             ResultSet rs = null;

             Account acc = null;

             try {

                    conn = JDBC_Util3.getConnection();

                    stm = conn.createStatement();

                    String sql = "select * from account where card_id = "

                    + toCardId;

                    System.out.println(sql);

                    rs = stm.executeQuery(sql);

                    while (rs.next()) {

                           acc = new Account();

                           acc.setCardId(rs.getString("card_id"));

                           acc.setPassword(rs.getString("password"));

                           acc.setBalance(rs.getDouble("balance"));

                           acc.setPhone(rs.getString("phone"));

                    }

             } catch (Exception e) {

             }finally{

                    JDBC_Util.release(rs, stm, null);

             }

             return acc;

       }

}

JDBC_Service.java

public class JDBC_Service {  

       public void transfer(Integer fromCardId,String password,

                    Integer toCardId,Double money){

             Connection conn = null;

             try{

                    conn = JDBC_Util2.getConnection();

                    //事务自动提交关闭

                    conn.setAutoCommit(false);

                    JDBC_Dao3 dao = new JDBC_Dao3();

                    //验证卡号是否存在

                    Account fromAcc = dao.queryAccount(fromCardId);

                    if(fromAcc == null){

                           throw new RuntimeException("卡号不存在");

                    }

                    //验证密码是否正确

                    if(null==password||!password.equals(fromAcc.getPassword())){

                           throw new RuntimeException("密码错误");

                    }

                    //验证余额

                    if(fromAcc.getBalance()<money){

                           throw new RuntimeException("余额不足");

                    }

                    //转出账户更新

                    fromAcc.setBalance(fromAcc.getBalance()-money);

                    dao.upDateAccount(fromAcc);

                    Account toAcc = dao.queryAccount(toCardId);

                    //验证到账卡号

                    if(toAcc ==null){

                           throw new RuntimeException("到账卡号不存在");

                    }

                    //转入账户更新

                    toAcc.setBalance(toAcc.getBalance()+money);

                    dao.upDateAccount(toAcc);

                    //提交事务

                    conn.commit();

             }catch(Exception e){

                    e.printStackTrace();

                    try {

                           conn.rollback();

                    } catch (SQLException e1) {

                           e1.printStackTrace();

                    }

             }finally{

                    JDBC_Util.release(null, null, conn);

             }

       }

}

最后main函数测试

             JDBC_Service sv  new JDBC_Service();

             sv.transfer(10002, "123321", 10004, 30.00);


转账成功

10002 -30  10004 +30

技术分享

=========================华丽丽的终结===========================

总结:虽然由于快节奏的开发,编程速度的追求,越爱越多的MVC框架出现,比如持久层的hibernate,

mybatis等等,他们对Dao层的支持都很强大,既 快速,又简便。但是他们的底层同样是使用了JDBC,

为了追求高速简便,我们可以不使用JDBC,但一定要了解JDBC。了解JDBC也有助于学习其他持久层框架。


以上就是我对JDBC全部心得。

限于文章篇幅原因,这里仅仅介绍冰山一角。由于笔者的水平有限,编写时间也很仓促,

文中难免会出现一些错误或者不准确的地方,不妥之处恳请读者批评指正。


本文出自 “心有猛虎,细嗅蔷薇” 博客,转载请与作者联系!

由浅到深学习JDBC三

标签:jdbc   threadlocal   jdbcutil   依赖注入   深入浅出   

原文地址:http://zhangdongxu.blog.51cto.com/12029530/1921710

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!