国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Spring之事務管理TranscationManager(大合集)

想到哪說到哪
事務四個特性:

  1. 原子性
    事務是數(shù)據(jù)庫的邏輯工作單位,事務中包括的諸操作要么全做,要么全不做。

  2. 一致性
    事務執(zhí)行的結果必須是使數(shù)據(jù)庫從一個一致性狀態(tài)變到另一個一致性狀態(tài)。一致性與原子性是密切相關的。

  3. 隔離性
    一個事務的執(zhí)行不能被其他事務干擾。

  4. 持續(xù)性
    一個事務一旦提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就應該是永久性的。

在正常的web項目中,事務和DAO一直如影隨行,所以有人認為配置事務和DAO的關系是密不可分,不能分離的。其實不然,DAO可以完全脫離容器獨立存在。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"     xmlns:mvc="http://www.springframework.org/schema/mvc"    xmlns:tx="http://www.springframework.org/schema/tx"    xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"    xsi:schemaLocation="    http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-3.2.xsd    http://www.springframework.org/schema/mvc    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd    http://www.springframework.org/schema/tx    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd    http://www.springframework.org/schema/aop    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd    http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring         http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">    <!-- 打開springmvc自動注解 -->    <mvc:annotation-driven />    <!-- 掃描的包 -->    <context:component-scan base-package="com.zhu" />    <!-- 數(shù)據(jù)源默認將autoCommit設置為true -->    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"        destroy-method="close"         p:driverClassName="com.mysql.jdbc.Driver"        p:username="zhu"        p:password="zhu" />    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"        p:dataSource-ref="dataSource" /></beans>
  • 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

zhu_test.sql

CREATE TABLE IF NOT EXISTS zhu_test (NAME VARCHAR(20),age INT(100)) ENGINE = INNODB;
  • 1

測試類:

package com.zhu.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import com.alibaba.druid.pool.DruidDataSource;@Service("service1")public class UserJdbcWithoutTransManagerService {    @Autowired    private JdbcTemplate jdbcTemplate;    public void addScore(String userName,int toAdd){        String sql = "UPDATE zhu_test u SET u.age = u.age + ? WHERE name =?";        jdbcTemplate.update(sql,toAdd,userName);    }    public static void main(String[] args) {        ApplicationContext ctx =         new ClassPathXmlApplicationContext("file:src/main/resources/applicationContext.xml");        UserJdbcWithoutTransManagerService service =             (UserJdbcWithoutTransManagerService)ctx.getBean("service1");        JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");        DruidDataSource druidDataSource = (DruidDataSource)jdbcTemplate.getDataSource();        //①.檢查數(shù)據(jù)源autoCommit的設置        System.out.println("autoCommit:"+ druidDataSource.isDefaultAutoCommit());        //②.插入一條記錄,初始分數(shù)為10        jdbcTemplate.execute(        "INSERT INTO zhu_test VALUES('tom',10)");        //③.調用工作在無事務環(huán)境下的服務類方法,將分數(shù)添加20分        service.addScore("tom",20);         //④.查看此時用戶的分數(shù)        @SuppressWarnings("deprecation")        int score = jdbcTemplate.queryForInt("SELECT age FROM zhu_test WHERE name ='tom'");        System.out.println("score:"+score);        jdbcTemplate.execute("DELETE FROM zhu_test WHERE name='tom'");    }}
  • 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

運行結果:

applicationContext.xml中并沒有配置事務,但是還是持久化到數(shù)據(jù)庫中去了。DataSource默認設置是自動提交的,也就是說,在執(zhí)行了CRUD之后,會馬上持久化到數(shù)據(jù)庫中。如果設置自動提交為false,那么在jdbcTemplate執(zhí)行完之后并不會馬上持久化到數(shù)據(jù)庫中,除非手動提交。
雖說沒有事務管理,程序依然可以進行數(shù)據(jù)的CRUD操作,但是沒有事務管理,在數(shù)據(jù)安全同步方面會面臨很大的挑戰(zhàn)。栗子太多,不一一舉例,看代碼
我們故意提交一條錯誤的sql語句

package com.zhu.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import com.alibaba.druid.pool.DruidDataSource;@Service("service1")public class UserJdbcWithoutTransManagerService {    @Autowired    private JdbcTemplate jdbcTemplate;    public void addScore(String userName,int toAdd){        String sql = "UPDATE zhu_test u SET u.age = u.age + ? WHERE name =?";        jdbcTemplate.update(sql,toAdd,userName);    }    public static void main(String[] args) {        ApplicationContext ctx =         new ClassPathXmlApplicationContext("file:src/main/resources/applicationContext.xml");        UserJdbcWithoutTransManagerService service =             (UserJdbcWithoutTransManagerService)ctx.getBean("service1");        JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");        DruidDataSource druidDataSource = (DruidDataSource)jdbcTemplate.getDataSource();        //①.檢查數(shù)據(jù)源autoCommit的設置        System.err.println("autoCommit:"+ druidDataSource.isDefaultAutoCommit());        //②.插入一條記錄,初始分數(shù)為10        jdbcTemplate.execute(        "INSERT INTO zhu_test VALUES('tom',10)");        //③.執(zhí)行一條錯誤sql語句        jdbcTemplate.execute(        "INSERT INTO zhu_test VALUES('tom1',10,00)");        //④.調用工作在無事務環(huán)境下的服務類方法,將分數(shù)添加20分(不會執(zhí)行)        service.addScore("tom",20);    }    }
  • 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

清空數(shù)據(jù),然后執(zhí)行結果是:②成功插入數(shù)據(jù)tom 10 然后③錯誤的sql拋出異常 然后④更新操作也不會執(zhí)行。
正常的邏輯是在同一方法或者類中執(zhí)行一系列的CRUD操作,其中一條出出現(xiàn)問題會拋出異常,然后已經(jīng)執(zhí)行完的語句回滾到發(fā)生異常之前的狀態(tài)。
這種情況在正常的開發(fā)環(huán)境是最基本的常識性錯誤,開發(fā)過程中一定要避免。
然后是配置事務。
applicationContext.xml文件中添加事務和模型視圖的配置

package com.zhu.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class NoTMController {    //②.自動注入JdbcTemplate    @Autowired    private JdbcTemplate jdbcTemplate;    //③.通過Spring MVC注解映URL請求    @RequestMapping("/logon")        @ResponseBody    public String logon(String userName,String password){        String sql = "UPDATE zhu_test u SET u.age = u.age + ? WHERE name =?";        if(isRightUser(userName,password)){            //執(zhí)行更新操作(年齡加20)            jdbcTemplate.update(sql,20,"tom");            //執(zhí)行錯誤語句            jdbcTemplate.execute(                "INSERT INTO zhu_test VALUES('tom1',10,00)");            return "success";        }else{            return "fail";        }    }    private boolean isRightUser(String userName,String password){        //do sth...        return true;    }}
  • 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

啟動項目 輸入網(wǎng)址
影響了一條數(shù)據(jù),操作已經(jīng)完成


檢測到錯誤,回滾

所以結果是數(shù)據(jù)沒有變化。
注釋掉錯誤的sql語句則完成執(zhí)行所有的sql語句。
事務在進行嵌套調用的時候不會分解為多個事務,比如說一個事務中的方法調用其他事務的方法不會產生多余的事務。
spring 對事務控制的支持統(tǒng)一在 TransactionDefinition 類中描述,該類有以下幾個重要的接口方法:
int getPropagationBehavior():事務的傳播行為
int getIsolationLevel():事務的隔離級別
int getTimeout():事務的過期時間
boolean isReadOnly():事務的讀寫特性。

所謂事務傳播行為就是多個事務方法相互調用時,事務如何在這些方法間傳播。Spring 支持 7 種事務傳播行為:

  • PROPAGATION_REQUIRED 如果當前沒有事務,就新建一個事務,如果已經(jīng)存在一個事務中,加入到這個事務中。這是最常見的選擇。
  • PROPAGATION_SUPPORTS 支持當前事務,如果當前沒有事務,就以非事務方式執(zhí)行
  • PROPAGATION_MANDATORY 使用當前的事務,如果當前沒有事務,就拋出異常
  • PROPAGATION_REQUIRES_NEW 新建事務,如果當前存在事務,把當前事務掛起。
  • PROPAGATION_NOT_SUPPORTED 以非事務方式執(zhí)行操作,如果當前存在事務,就把當前事務掛起。
  • PROPAGATION_NEVER 以非事務方式執(zhí)行,如果當前存在事務,則拋出異常。

Spring 默認的事務傳播行為是 PROPAGATION_REQUIRED,它適合于絕大多數(shù)的情況。假設 ServiveX#methodX() 都工作在事務環(huán)境下(即都被 Spring 事務增強了),假設程序中存在如下的調用鏈:Service1#method1()->Service2#method2()->Service3#method3(),那么這 3 個服務類的 3 個方法通過 Spring 的事務傳播機制都工作在同一個事務中。

事務與線程
由于 Spring 的事務管理器是通過線程相關的 ThreadLocal 來保存數(shù)據(jù)訪問基礎設施,再結合 IOC 和 AOP 實現(xiàn)高級聲明式事務的功能,所以 Spring 的事務天然地和線程有著千絲萬縷的聯(lián)系。

我們知道 Web 容器本身就是多線程的,Web 容器為一個 Http 請求創(chuàng)建一個獨立的線程,所以由此請求所牽涉到的 Spring 容器中的 Bean 也是運行于多線程的環(huán)境下。在絕大多數(shù)情況下,Spring 的 Bean 都是單實例的(singleton),單實例 Bean 的最大的好處是線程無關性,不存在多線程并發(fā)訪問的問題,也即是線程安全的。

一個類能夠以單實例的方式運行的前提是“無狀態(tài)”:即一個類不能擁有狀態(tài)化的成員變量。我們知道,在傳統(tǒng)的編程中,DAO 必須執(zhí)有一個 Connection,而 Connection 即是狀態(tài)化的對象。所以傳統(tǒng)的 DAO 不能做成單實例的,每次要用時都必須 new 一個新的實例。傳統(tǒng)的 Service 由于將有狀態(tài)的 DAO 作為成員變量,所以傳統(tǒng)的 Service 本身也是有狀態(tài)的。

但是在 Spring 中,DAO 和 Service 都以單實例的方式存在。Spring 是通過 ThreadLocal 將有狀態(tài)的變量(如 Connection 等)本地線程化,達到另一個層面上的“線程無關”,從而實現(xiàn)線程安全。Spring 不遺余力地將狀態(tài)化的對象無狀態(tài)化,就是要達到單實例化 Bean 的目的。

由于 Spring 已經(jīng)通過 ThreadLocal 的設施將 Bean 無狀態(tài)化,所以 Spring 中單實例 Bean 對線程安全問題擁有了一種天生的免疫能力。不但單實例的 Service 可以成功運行于多線程環(huán)境中,Service 本身還可以自由地啟動獨立線程以執(zhí)行其它的 Service。

于是我們修改我們的代碼

package com.zhu.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class NoTMController {    //②.自動注入JdbcTemplate    @Autowired    private JdbcTemplate jdbcTemplate;    //③.通過Spring MVC注解映URL請求    @RequestMapping("/logon")        @ResponseBody    public String logon(String userName,String password){        System.err.println(userName);        if(isRightUser(userName,password)){           Thread h1 = new Thread(){               String sql = "UPDATE zhu_test u SET u.age = u.age + ? WHERE name =?";                @Override                public void run() {                     jdbcTemplate.update(sql,20,"tom");                }            };            h1.start();            jdbcTemplate.execute(                    "INSERT INTO zhu_test VALUES('tom1',10,00)");            return "success";        }else{            return "fail";        }    }    private boolean isRightUser(String userName,String password){        //do sth...        return true;    }}
  • 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

代碼還是原來的代碼,只是將更新年齡的操作放到其他線程中,然后再進項上面的操作。
結果就是更新成功,插入失敗,拋出異常。
在相同線程中進行相互嵌套調用的事務方法工作于相同的事務中。如果這些相互嵌套調用的方法工作在不同的線程中,不同線程下的事務方法工作在獨立的事務中。

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Spring 事務管理高級應用難點剖析: 第 1 部分
Spring JDBC
spring3之JdbcTemplate詳解
spring tx:advice 和 aop:config
數(shù)據(jù)庫事務 | JDBC中使用事務 | spring中的事務管理
Spring 使用 XML 配置聲明式事務
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服