事務數據庫連接池DBCP和C3P0與工具類DBUtils

      網友投稿 831 2022-05-29

      文章目錄

      事務

      使用命令行方式演示事務。

      使用代碼方式演示事務

      事務的特性

      事務的安全隱患

      讀未提交 演示

      讀已提交演示

      可串行化

      事務總結

      需要掌握的

      需要了解的

      安全隱患

      隔離級別

      丟失更新

      解決丟失更新

      數據庫連接池

      自定義數據庫連接池

      解決自定義數據庫連接池出現的問題。

      如何擴展某一個方法?

      開源連接池

      DBCP

      C3P0

      不使用配置文件方式

      使用配置文件方式

      DBUtils

      增刪改

      查詢

      ResultSetHandler 常用的實現類

      總結

      事務

      數據連接池

      DBUtils

      事務

      Transaction 其實指的一組操作,里面包含許多個單一的邏輯。只要有一個邏輯沒有執行成功,那么都算失敗。 所有的數據都回歸到最初的狀態(回滾)

      為什么要有事務?

      為了確保邏輯的成功。 例子: 銀行的轉賬。

      使用命令行方式演示事務。

      開啟事務

      start transaction;

      提交或者回滾事務

      commit; 提交事務, 數據將會寫到磁盤上的數據庫

      rollback ; 數據回滾,回到最初的狀態。

      關閉自動提交功能。

      演示事務

      使用代碼方式演示事務

      代碼里面的事務,主要是針對連接來的。

      通過conn.setAutoCommit(false )來關閉自動提交的設置。

      提交事務 conn.commit();

      回滾事務 conn.rollback();

      @Test public void testTransaction(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConn(); //連接,事務默認就是自動提交的。 關閉自動提交。 conn.setAutoCommit(false); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); //扣錢, 扣ID為1 的100塊錢 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); int a = 10 /0 ; //加錢, 給ID為2 加100塊錢 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); //成功: 提交事務。 conn.commit(); } catch (SQLException e) { try { //事變: 回滾事務 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtil.release(conn, ps, rs); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      事務的特性

      原子性

      指的是 事務中包含的邏輯,不可分割。

      一致性

      指的是 事務執行前后。數據完整性

      隔離性

      指的是 事務在執行期間不應該受到其他事務的影響

      持久性

      指的是 事務執行成功,那么數據應該持久保存到磁盤上。

      事務的安全隱患

      不考慮隔離級別設置,那么會出現以下問題。

      臟讀 不可重讀讀 幻讀.

      * 臟讀 > 一個事務讀到另外一個事務還未提交的數據 * 不可重復讀 > 一個事務讀到了另外一個事務提交的數據 ,造成了前后兩次查詢結果不一致。

      1

      2

      3

      4

      5

      6

      7

      設置A窗口的隔離級別為 讀未提交

      兩個窗口都分別開啟事務

      丟失更新

      設置A窗口的隔離級別為 讀已提交

      A B 兩個窗口都開啟事務, 在B窗口執行更新操作。

      在A窗口執行的查詢結果不一致。 一次是在B窗口提交事務之前,一次是在B窗口提交事務之后。

      這個隔離級別能夠屏蔽 臟讀的現象, 但是引發了另一個問題 ,不可重復讀。

      可串行化

      如果有一個連接的隔離級別設置為了串行化 ,那么誰先打開了事務, 誰就有了先執行的權利, 誰后打開事務,誰就只能得著,等前面的那個事務,提交或者回滾后,才能執行。 但是這種隔離級別一般比較少用。 容易造成性能上的問題。 效率比較低。

      按效率劃分,從高到低

      讀未提交 > 讀已提交 > 可重復讀 > 可串行化

      按攔截程度 ,從高到底

      可串行化 > 可重復讀 > 讀已提交 > 讀未提交

      事務總結

      需要掌握的

      在代碼里面會使用事務

      conn.setAutoCommit(false); conn.commit(); conn.rollback();

      1

      2

      3

      4

      5

      6

      事務只是針對連接連接對象,如果再開一個連接對象,那么那是默認的提交。

      事務是會自動提交的。

      需要了解的

      讀 臟讀 一個事務讀到了另一個事務未提交的數據 不可重復讀 一個事務讀到了另一個事務已提交的數據,造成前后兩次查詢結果不一致 幻讀 一個事務讀到了另一個事務insert的數據 ,造成前后查詢結果不一致 。 寫 丟失更新。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      讀未提交

      引發問題: 臟讀

      讀已提交

      解決: 臟讀 , 引發: 不可重復讀

      可重復讀

      解決: 臟讀 、 不可重復讀 , 未解決: 幻讀

      可串行化

      解決: 臟讀、 不可重復讀 、 幻讀。

      mySql 默認的隔離級別是 可重復讀

      Oracle 默認的隔離級別是 讀已提交

      丟失更新

      解決丟失更新

      悲觀鎖

      可以在查詢的時候,加入 for update

      樂觀鎖

      要求程序員自己控制。

      數據庫連接池

      數據庫的連接對象創建工作,比較消耗性能。

      2.一開始先在內存中開辟一塊空間(集合) , 往池子里面放置多個連接對象。后面需要連接的話,直接從池子里面去獲取。不用自己去創建連接了。 使用完畢, 要記得歸還連接。確保連接對象能循環利用。

      自定義數據庫連接池

      代碼實現

      出現的問題:

      需要額外記住 addBack方法

      單例。

      無法面向接口編程。

      UserDao dao = new UserDaoImpl();

      dao.insert();

      DataSource dataSource = new MyDataSource();

      因為接口里面沒有定義addBack方法。

      怎么解決? 以addBack 為切入點。

      解決自定義數據庫連接池出現的問題。

      由于多了一個addBack 方法,所以使用這個連接池的地方,需要額外記住這個方法,并且還不能面向接口編程。

      我們打算修改接口中的那個close方法。 原來的Connection對象的close方法,是真的關閉連接。

      打算修改這個close方法,以后在調用close, 并不是真的關閉,而是歸還連接對象。

      如何擴展某一個方法?

      原有的方法邏輯,不是我們想要的。 要修改自己的邏輯

      直接改源碼 無法實現。

      繼承, 必須得知道這個接口的具體實現是誰。

      使用裝飾者模式。

      開源連接池

      導入jar文件

      不使用配置文件:

      public void testDBCP01(){ Connection conn = null; PreparedStatement ps = null; try { //1. 構建數據源對象 BasicDataSource dataSource = new BasicDataSource(); //連的是什么類型的數據庫, 訪問的是哪個數據庫 , 用戶名, 密碼。。 //jdbc:mysql://localhost/bank 主協議:子協議 ://本地/數據庫 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost/bank"); dataSource.setUsername("root"); dataSource.setPassword("123456"); //2. 得到連接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admin"); ps.setInt(2, 1000); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      使用配置文件方式:

      Connection conn = null; PreparedStatement ps = null; try { BasicDataSourceFactory factory = new BasicDataSourceFactory(); Properties properties = new Properties(); InputStream is = new FileInputStream("src//dbcpconfig.properties"); properties.load(is); DataSource dataSource = factory.createDataSource(properties); //2. 得到連接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "liangchaowei"); ps.setInt(2, 100); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      事務與數據庫連接池DBCP和C3P0與工具類DBUtils

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      C3P0

      拷貝jar文件 到 lib目錄

      不使用配置文件方式

      Connection conn = null; PreparedStatement ps = null; try { //1. 創建datasource ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 設置連接數據的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); //忘記了---> 去以前的代碼 ---> jdbc的文檔 dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("root"); //2. 得到連接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      使用配置文件方式

      //默認會找 xml 中的 default-config 分支。 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 設置連接數據的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("123456"); //2. 得到連接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200);

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      DBUtils

      增刪改

      //dbutils 只是幫我們簡化了CRUD 的代碼, 但是連接的創建以及獲取工作。 不在他的考慮范圍 QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); //增加 //queryRunner.update("insert into account values (null , ? , ? )", "aa" ,1000); //刪除 //queryRunner.update("delete from account where id = ?", 5); //更新 //queryRunner.update("update account set money = ? where id = ?", 10000000 , 6);

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      查詢

      直接new接口的匿名實現類

      QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler(){ @Override public Account handle(ResultSet rs) throws SQLException { Account account = new Account(); while(rs.next()){ String name = rs.getString("name"); int money = rs.getInt("money"); account.setName(name); account.setMoney(money); } return account; } }, 6); System.out.println(account.toString());

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      直接使用框架已經寫好的實現類。

      查詢單個對象

      QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());

      //查詢單個對象

      Account account = queryRunner.query(“select * from account where id = ?”,

      new BeanHandler(Account.class), 8);

      查詢多個對象

      QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());

      List list = queryRunner.query("select * from account ",

      new BeanListHandler(Account.class));

      ResultSetHandler 常用的實現類

      以下兩個是使用頻率最高的

      BeanHandler, 查詢到的單個數據封裝成一個對象 BeanListHandler, 查詢到的多個數據封裝 成一個List<對象>

      1

      2

      ArrayHandler, 查詢到的單個數據封裝成一個數組 ArrayListHandler, 查詢到的多個數據封裝成一個集合 ,集合里面的元素是數組。 MapHandler, 查詢到的單個數據封裝成一個map MapListHandler,查詢到的多個數據封裝成一個集合 ,集合里面的元素是map。

      1

      2

      3

      4

      5

      6

      7

      ColumnListHandler

      KeyedHandler

      ScalarHandler

      總結

      事務

      使用命令行演示 使用代碼演示

      1

      2

      3

      臟讀、

      不可重復讀、

      幻讀

      丟失更新

      悲觀鎖 樂觀鎖 4個隔離級別 讀未提交 讀已提交 可重復讀 可串行化

      1

      2

      3

      4

      5

      6

      7

      8

      數據連接池

      DBCP

      不使用配置

      使用配置

      C3P0

      不使用配置

      使用配置 (必須掌握)

      自定義連接池

      裝飾者模式

      DBUtils

      簡化了我們的CRUD , 里面定義了通用的CRUD方法。

      queryRunner.update(); queryRunner.query

      1

      2

      數據庫

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Maven入門指南 :Maven 快速入門及簡單使用
      下一篇:MySQL這樣學才叫了解!【4】
      相關文章
      国产精品亚洲专一区二区三区| 久久久久无码专区亚洲av| 亚洲av永久综合在线观看尤物| 大胆亚洲人体视频| 亚洲AV色香蕉一区二区| 亚洲第一区在线观看| 无码乱人伦一区二区亚洲| 大桥未久亚洲无av码在线| 亚洲一区二区三区免费观看| 精品亚洲一区二区三区在线播放| 亚洲香蕉久久一区二区 | 亚洲国产精品狼友中文久久久| 亚洲一级免费视频| 亚洲天堂电影在线观看| 亚洲经典千人经典日产| 亚洲偷自拍另类图片二区| 久久精品国产亚洲av成人| 亚洲国产精品综合久久久| 亚洲视频人成在线播放| 亚洲视频在线一区| 亚洲精品伊人久久久久| 亚洲国产天堂久久综合| 狠狠色婷婷狠狠狠亚洲综合| 4444亚洲国产成人精品| 亚洲欧美日韩综合俺去了| 亚洲午夜无码毛片av久久京东热| 久久国产亚洲观看| 国产精品亚洲产品一区二区三区 | 亚洲色大成网站www永久| 久久亚洲国产成人精品无码区| 亚洲综合小说另类图片动图 | 国产成人麻豆亚洲综合无码精品| 亚洲自偷自偷在线制服| 亚洲日韩人妻第一页| 亚洲国产精品毛片av不卡在线| 久久伊人久久亚洲综合| 午夜亚洲乱码伦小说区69堂| 亚洲va成无码人在线观看| 九九精品国产亚洲AV日韩| 亚洲人成网站在线观看播放| 7777久久亚洲中文字幕|