本打算系列之一把此次寫的大綱列出來呢,無奈本身沒想好,只有大體定一個方向,待後面補充,或者從新組織這一系列。
java
作幾個概念的澄清和一些基礎東西的介紹node
一、假設你熟悉JDBC提供的api操做,好比:mysql
JDBC提供的事務處理API很是少,請不要被Spring中事務處理的那一堆源代碼所打擊得信心盡失,這些框架提供的事務處理功能歸根結底主要經過以Connection類的方法完成:spring
Connection.setAutoCommit(boolean); Connection.commit(); Connection.rollback();
二、本地事務和分佈式事務sql
本地(Local Transaction)事務指只有一個數據源參與的事務,好比只有數據庫或者只有JMS;分佈式事務(Distributed Transaction)指有多個數據源同時參與的事務,好比一項操做須要同時訪問數據庫和經過JMS發送消息,或者一項操做須要同時訪問兩個不一樣數據庫。對於分佈式事務,Java提供了JTA規範,它的原理與本地事務存在不一樣。 鑑於多數狀況下Java事務爲本地事務。數據庫
三、線程安全的基礎api
爲何會扯到線程安全呢,由於一次DB的鏈接是Connection對象決定的,同一個Connection對象,有可能會同事被多個Thread訪問,同時瞭解ThreadLocal【1】來解決多線程之間的共享問題。
安全
四、Spring 事務管理系列之一(JDBC的事務管理例子)多線程
這個是開篇,經過這個系列一,會直觀的展現一下事務,給剛接觸的同窗一點直觀的感知,固然可能有本身理解不當的地方,也請大牛指出。框架
本文將使用兩張表來演示事務的處理過程,怎麼來證實事務在執行了呢?通常狀況下是save以後數據庫db能看獲得,可是這不能證實事務起做用了,這個例子中會經過使用插入一張customer表,一張Address表,在插入customer表以後,拋出異常,在插入address表,這兩個操做是放在一個事務裏面的,若是最後表裏面沒有數據,則代表,事務確實起做用啦,要麼全插,要麼不插。
4.一、建立database
customer.sql
CREATE TABLE `Customer` ( `id` int(11) unsigned NOT NULL, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
address.sql
CREATE TABLE `Address` ( `id` int(11) unsigned NOT NULL, `address` varchar(20) DEFAULT NULL, `country` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
數據庫表結構:
4.二、項目使用maven進行管理,因爲本項目使用jdbc鏈接mysql,因此包含mysql-connector-java,spring-tx,由於要實用JDBCTemplate因此又包括spring-jdbc其餘依賴以下:
<properties> <!-- Generic properties --> <java.version>1.6</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- Spring --> <spring-framework.version>3.0.6.RELEASE</spring-framework.version> <!-- Logging --> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.5</slf4j.version> <!-- Test --> <junit.version>4.11</junit.version> </properties> <dependencies> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.1</version> </dependency> <!-- Spring JDBC and MySQL Driver --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.5</version> </dependency> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> <scope>runtime</scope> </dependency> <!-- Test Artifacts --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring-framework.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies>
4.三、具體實現
關於spring.xml bean的配置,還有pojo的配置很少作介紹。主要提出來事務處理的邏輯:
public void create(Customer customer) { String queryCustomer = "insert into Customer (id, name) values (?,?)"; String queryAddress = "insert into Address (id, address,country) values (?,?,?)"; JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.update(queryCustomer, new Object[] { customer.getId(), customer.getName() }); System.out.println("Inserted into Customer Table Successfully"); jdbcTemplate.update(queryAddress, new Object[] { customer.getId(), customer.getAddress().getAddress(), customer.getAddress().getCountry() }); System.out.println("Inserted into Address Table Successfully"); }
可見,customer表插入以後,打印「Inserted into Customer Table Successfully」而後再插入Address那張表,咱們在設計Address這張表的時候要求Address的地址字段是小於20 chars的長度,咱們在測試代碼裏面故意構造,大於20的長度,讓其拋出異常,代碼以下:
Customer customer = new Customer(); customer.setId(2); customer.setName("lianzi"); Address address = new Address(); address.setId(2); address.setCountry("china"); // setting value more than 20 chars, so that SQLException occurs address.setAddress("********************************************"); customer.setAddress(address); return customer;
運行結果:
同時查看,數據庫發現customer表中,並沒有數據,符合預期,代表事務生效啦。
五、問題和思考?
spring是如何實現事務管理的呢?下面幾篇文章,會實現一個很簡單的相似spring事務管理的功能。
代碼下載