由淺到深學習JDBC三


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

wKioL1kJpaKgh2dbAABWthIITdw473.png-wh_50

=========================華麗麗的終結===========================

總結:雖然由於快節奏的開發,編程速度的追求,越愛越多的MVC框架出現,比如持久層的hibernate,

mybatis等等,他們對Dao層的支持都很強大,既 快速,又簡便。但是他們的底層同樣是使用了JDBC,

爲了追求高速簡便,我們可以不使用JDBC,但一定要了解JDBC。瞭解JDBC也有助於學習其他持久層框架。


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

限於文章篇幅原因,這裏僅僅介紹冰山一角。由於筆者的水平有限,編寫時間也很倉促,

文中難免會出現一些錯誤或者不準確的地方,不妥之處懇請讀者批評指正。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章