摘要:元數據什么是元數據元數據其實就是數據庫,表,列的定義信息為什么我們要用元數據即使我們寫了一個簡單工具類,我們的代碼還是非常冗余。我們要使用元數據獲取結果集的信息,才能對結果集進行操作。
1.事務
一個SESSION所進行的所有更新操作要么一起成功,要么一起失敗
舉個例子:A向B轉賬,轉賬這個流程中如果出現問題,事務可以讓數據恢復成原來一樣【A賬戶的錢沒變,B賬戶的錢也沒變】。
事例說明:
/* * 我們來模擬A向B賬號轉賬的場景 * A和B賬戶都有1000塊,現在我讓A賬戶向B賬號轉500塊錢 * * */ //JDBC默認的情況下是關閉事務的,下面我們看看關閉事務去操作轉賬操作有什么問題 //A賬戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //B賬戶多了500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
從上面看,我們的確可以發現A向B轉賬,成功了。可是如果A向B轉賬的過程中出現了問題呢?下面模擬一下
//A賬戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //這里模擬出現問題 int a = 3 / 0; String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
顯然,上面代碼是會拋出異常的,我們再來查詢一下數據。A賬戶少了500塊錢,B賬戶的錢沒有增加。這明顯是不合理的。
我們可以通過事務來解決上面出現的問題
//開啟事務,對數據的操作就不會立即生效。 connection.setAutoCommit(false); //A賬戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //在轉賬過程中出現問題 int a = 3 / 0; //B賬戶多500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate(); //如果程序能執行到這里,沒有拋出異常,我們就提交數據 connection.commit(); //關閉事務【自動提交】 connection.setAutoCommit(true); } catch (SQLException e) { try { //如果出現了異常,就會進到這里來,我們就把事務回滾【將數據變成原來那樣】 connection.rollback(); //關閉事務【自動提交】 connection.setAutoCommit(true); } catch (SQLException e1) { e1.printStackTrace(); }
上面的程序也一樣拋出了異常,A賬戶錢沒有減少,B賬戶的錢也沒有增加。
注意:當Connection遇到一個未處理的SQLException時,系統會非正常退出,事務也會自動回滾,但如果程序捕獲到了異常,是需要在catch中顯式回滾事務的。
savapoint我們還可以使用savepoint設置中間點。如果在某地方出錯了,我們設置中間點,回滾到出錯之前即可。
應用場景:現在我們要算一道數學題,算到后面發現算錯數了。前面的運算都是正確的,我們不可能重頭再算【直接rollback】,最好的做法就是在保證前面算對的情況下,設置一個保存點。從保存點開始重新算。
注意:savepoint不會結束當前事務,普通提交和回滾都會結束當前事務的
事務的隔離級別數據庫定義了4個隔離級別:
Serializable【可避免臟讀,不可重復讀,虛讀】
Repeatable read【可避免臟讀,不可重復讀】
Read committed【可避免臟讀】
Read uncommitted【級別最低,什么都避免不了】
分別對應Connection類中的4個常量
TRANSACTION_READ_UNCOMMITTED
TRANSACTION_READ_COMMITTED
TRANSACTION_REPEATABLE_READ
TRANSACTION_SERIALIZABLE
臟讀:一個事務讀取到另外一個事務未提交的數據
例子:A向B轉賬,A執行了轉賬語句,但A還沒有提交事務,B讀取數據,發現自己賬戶錢變多了!B跟A說,我已經收到錢了。A回滾事務【rollback】,等B再查看賬戶的錢時,發現錢并沒有多。
不可重復讀:一個事務讀取到另外一個事務已經提交的數據,也就是說一個事務可以看到其他事務所做的修改
注:A查詢數據庫得到數據,B去修改數據庫的數據,導致A多次查詢數據庫的結果都不一樣【危害:A每次查詢的結果都是受B的影響的,那么A查詢出來的信息就沒有意思了】
虛讀(幻讀):是指在一個事務內讀取到了別的事務插入的數據,導致前后讀取不一致。
注:和不可重復讀類似,但虛讀(幻讀)會讀到其他事務的插入的數據,導致前后讀取不一致
簡單總結:臟讀是不可容忍的,不可重復讀和虛讀在一定的情況下是可以的【做統計的肯定就不行】。
2.元數據 什么是元數據元數據其實就是數據庫,表,列的定義信息
為什么我們要用元數據即使我們寫了一個簡單工具類,我們的代碼還是非常冗余。對于增刪改而言,只有SQL和參數是不同的,我們為何不把這些相同的代碼抽取成一個方法?對于查詢而言,不同的實體查詢出來的結果集是不一樣的。我們要使用元數據獲取結果集的信息,才能對結果集進行操作。
ParameterMetaData --參數的元數據
ResultSetMetaData --結果集的元數據
DataBaseMetaData --數據庫的元數據
3.改造JDBC工具類問題:我們對數據庫的增刪改查都要連接數據庫,關閉資源,獲取PreparedSteatment對象,獲取Connection對象此類的操作,這樣的代碼重復率是極高的,所以我們要對工具類進行增強
增刪改//我們發現,增刪改只有SQL語句和傳入的參數是不知道的而已,所以讓調用該方法的人傳遞進來 //由于傳遞進來的參數是各種類型的,而且數目是不確定的,所以使用Object[] public static void update(String sql, Object[] objects) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = getConnection(); preparedStatement = connection.prepareStatement(sql); //根據傳遞進來的參數,設置SQL占位符的值 for (int i = 0; i < objects.length; i++) { preparedStatement.setObject(i + 1, objects[i]); } //執行SQL語句 preparedStatement.executeUpdate(); } catch (Exception e) { e.printStackTrace();查詢
/* 1:對于查詢語句來說,我們不知道對結果集進行什么操作【常用的就是把數據封裝成一個Bean對象,封裝成一個List集合】 2:我們可以定義一個接口,讓調用者把接口的實現類傳遞進來 3:這樣接口調用的方法就是調用者傳遞進來實現類的方法。【策略模式】 */ //這個方法的返回值是任意類型的,所以定義為Object。 public static Object query(String sql, Object[] objects, ResultSetHandler rsh) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = getConnection(); preparedStatement = connection.prepareStatement(sql); //根據傳遞進來的參數,設置SQL占位符的值 if (objects != null) { for (int i = 0; i < objects.length; i++) { preparedStatement.setObject(i + 1, objects[i]); } } resultSet = preparedStatement.executeQuery(); //調用調用者傳遞進來實現類的方法,對結果集進行操作 return rsh.hanlder(resultSet); }
接口:
/* * 定義對結果集操作的接口,調用者想要對結果集進行什么操作,只要實現這個接口即可 * */ public interface ResultSetHandler { Object hanlder(ResultSet resultSet); }
實現類:
//接口實現類,對結果集封裝成一個Bean對象 public class BeanHandler implements ResultSetHandler { //要封裝成一個Bean對象,首先要知道Bean是什么,這個也是調用者傳遞進來的。 private Class clazz; public BeanHandler(Class clazz) { this.clazz = clazz; } @Override public Object hanlder(ResultSet resultSet) { try { //創建傳進對象的實例化 Object bean = clazz.newInstance(); if (resultSet.next()) { //拿到結果集元數據 ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) { //獲取到每列的列名 String columnName = resultSetMetaData.getColumnName(i+1); //獲取到每列的數據 String columnData = resultSet.getString(i+1); //設置Bean屬性 Field field = clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(bean,columnData); } //返回Bean對象 return bean; }
樂于分享和輸出干貨的Java技術公眾號:Java3y。
文章的目錄導航:
https://github.com/ZhongFuCheng3y/3y
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68507.html
摘要:前言由于寫的文章已經是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 前言 由于寫的文章已經是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導航哦~想要獲取最新原創的技術文章歡迎關注我的公眾號:Java3y Java3y文章目錄導航 Java基礎 泛型就這么簡單 注解就這么簡單 Druid數據庫連接池...
摘要:連接對象執行命令對象執行關閉值得注意的是,對數據庫連接池是有很好的支持的。給我們提供了事務的管理器類,事務管理器類又分為兩種,因為的事務和的事務是不一樣的。 前言 上一篇Spring博文主要講解了如何使用Spring來實現AOP編程,本博文主要講解Spring的DAO模塊對JDBC的支持,以及Spring對事務的控制... 對于JDBC而言,我們肯定不會陌生,我們在初學的時候肯定寫過非...
摘要:常用的方法創建向數據庫發送的對象。創建執行存儲過程的對象設置事務自動提交提交事務回滾事務對象對象用于向數據庫發送語句,對數據庫的增刪改查都可以通過此對象發送語句完成。 1.什么是JDBC JDBC全稱為:Java Data Base Connectivity,它是可以執行SQL語句的Java API 2.為什么我們要用JDBC 市面上有非常多的數據庫,本來我們是需要根據不同的數據庫學...
摘要:使用執行單元測試查詢獲取連接對象根據連接對象,得到執行語句,返回遍歷結果集查詢獲取連接對象根據連接對象,得到執行添加影響的行數,,如果大于表明操作成功。否則失敗更新成功更新失敗光標選中方法名字,然后右鍵執行單元測試。 文章有不當之處,歡迎指正,如果喜歡微信閱讀,你也可以關注我的微信公眾號:好好學java,獲取優質學習資源。 一、JDBC JAVA Database Connectivi...
摘要:一配置屬性詳解可以在各式各樣不同環境下工作而設計的因此存在著大量的配置參數。以簡便操作,多數配置參數都有默認的配置值也是我們日常使用的必須品。 Hibernate (開放源代碼的對象關系映射框架) Hibernate是一個開放源代碼的對象關系映射框架,它對JDBC進行了非常輕量級的對象封裝, 它將POJO與數據庫表建立映射關系,是一個全自動的orm框架,hibernat...
閱讀 992·2021-11-23 09:51
閱讀 3481·2021-11-22 12:04
閱讀 2725·2021-11-11 16:55
閱讀 2950·2019-08-30 15:55
閱讀 3236·2019-08-29 14:22
閱讀 3360·2019-08-28 18:06
閱讀 1249·2019-08-26 18:36
閱讀 2136·2019-08-26 12:08