事務管理
一個數據庫事務是一個單一的工作單元操作序列。這些操作應該要么完整地執行,要么完全不執行。事務管理是一個重要組成部分,事務管理可以確保數據完整性和一致性。事務具有以下四個關鍵特性分別是 ACID:
-
原子性:事務應該當作一個單獨單元的操作,這意味着整個序列操作要么是成功,要么是失敗的。
-
一致性:這表示數據庫的引用完整性的一致性,表中唯一的主鍵等。
-
隔離性:可能同時處理很多有相同的數據集的事務,每個事務應該與其他事務隔離,以防止數據損壞。
- 持久性:一個事務一旦完成全部操作后,這個事務的結果必須是永久性的,不能因系統故障而從數據庫中刪除。
一個真正的關系型數據庫管理系統應該為每個事務保證所有的四個特性。使用 SQL 發布到數據庫中的事務的簡單視圖如下:
-
使用 begin transaction 命令開始事務。
-
使用 SQL 查詢語句執行各種刪除、更新或插入操作。
- 如果所有的操作都成功,則執行提交操作,否則回滾所有操作。
Spring 支持編程式和聲明式事務管理。EJB 需要一個應用程序服務器,但 Spring 事務管理可以在不需要應用程序服務器的情況下實現。
編程式 vs. 聲明式
Spring 支持兩種類型的事務管理:
-
編程式事務管理 :這意味着你在編程的幫助下有管理事務。這給了你極大的靈活性,但卻很難維護。
- 聲明式事務管理 :這意味着你從業務代碼中分離事務管理。你僅僅使用注解或 XML 配置來管理事務。
聲明式事務管理比編程式事務管理更可取,盡管它不如編程式事務管理靈活,但它允許你通過代碼控制事務。但作為一種橫切關注點,聲明式事務管理可以使用 AOP 方法進行模塊化。Spring 支持使用 Spring AOP 框架的聲明式事務管理。
Spring 事務抽象
Spring 事務抽象的關鍵是由 org.springframework.transaction.PlatformTransactionManager 接口定義,如下所示:
1 public interface PlatformTransactionManager { 2 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; 3 void commit(TransactionStatus status) throws TransactionException; 4 void rollback(TransactionStatus status) throws TransactionException; 5 }
TransactionStatus getTransaction(TransactionDefinition definition):根據指定的傳播行為,該方法返回當前活動事務或創建一個新的事務。
void commit(TransactionStatus status):該方法提交給定的事務和關於它的狀態。
void rollback(TransactionStatus status):該方法執行一個給定事務的回滾。
TransactionDefinition 是在 Spring 中事務支持的核心接口,它的定義如下:
1 public interface TransactionDefinition { 2 int getPropagationBehavior(); 3 int getIsolationLevel(); 4 String getName(); 5 int getTimeout(); 6 boolean isReadOnly(); 7 }
int getPropagationBehavior():該方法返回傳播行為。Spring 提供了與 EJB CMT 類似的所有的事務傳播選項。
int getIsolationLevel():該方法返回該事務獨立於其他事務的工作的程度。
String getName():該方法返回該事務的名稱。
int getTimeout():該方法返回以秒為單位的時間間隔,事務必須在該時間間隔內完成。
boolean isReadOnly():該方法返回該事務是否是只讀的。
下面是隔離級別的可能值:
TransactionDefinition.ISOLATION_DEFAULT:這是默認的隔離級別。
TransactionDefinition.ISOLATION_READ_COMMITTED:表明能夠阻止誤讀;可以發生不可重復讀和虛讀。
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:表明可以發生誤讀、不可重復讀和虛讀。
TransactionDefinition.ISOLATION_REPEATABLE_READ:表明能夠阻止誤讀和不可重復讀;可以發生虛讀。
TransactionDefinition.ISOLATION_SERIALIZABLE:表明能夠阻止誤讀、不可重復讀和虛讀。
下面是傳播類型的可能值:
TransactionDefinition.PROPAGATION_MANDATORY:支持當前事務;如果不存在當前事務,則拋出一個異常。
TransactionDefinition.PROPAGATION_NESTED:如果存在當前事務,則在一個嵌套的事務中執行。
TransactionDefinition.PROPAGATION_NEVER:不支持當前事務;如果存在當前事務,則拋出一個異常。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:不支持當前事務;而總是執行非事務性。
TransactionDefinition.PROPAGATION_REQUIRED:支持當前事務;如果不存在事務,則創建一個新的事務。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新事務,如果存在一個事務,則把當前事務掛起。
TransactionDefinition.PROPAGATION_SUPPORTS:支持當前事務;如果不存在,則執行非事務性。
TransactionDefinition.TIMEOUT_DEFAULT:使用默認超時的底層事務系統,或者如果不支持超時則沒有。
TransactionStatus 接口為事務代碼提供了一個簡單的方法來控制事務的執行和查詢事務狀態。
1 public interface TransactionStatus extends SavepointManager { 2 boolean isNewTransaction(); 3 boolean hasSavepoint(); 4 void setRollbackOnly(); 5 boolean isRollbackOnly(); 6 boolean isCompleted(); 7 }
boolean hasSavepoint():該方法返回該事務內部是否有一個保存點,也就是說,基於一個保存點已經創建了嵌套事務。
boolean isCompleted():該方法返回該事務是否完成,也就是說,它是否已經提交或回滾。
boolean isNewTransaction():在當前事務是新的情況下,該方法返回 true。
boolean isRollbackOnly():該方法返回該事務是否已標記為 rollback-only。
void setRollbackOnly():該方法設置該事務為 rollback-only 標記。
Spring 編程式事務管理
編程式事務管理方法允許你在對你的源代碼編程的幫助下管理事務。這給了你極大地靈活性,但是它很難維護。
在我們開始之前,至少要有兩個數據庫表,在事務的幫助下我們可以執行多種 CRUD 操作。以 Student 表為例,用下述 DDL 可以在 MySQL TEST 數據庫中創建該表:
1 CREATE TABLE Student( 2 ID INT NOT NULL AUTO_INCREMENT, 3 NAME VARCHAR(20) NOT NULL, 4 AGE INT NOT NULL, 5 PRIMARY KEY (ID) 6 );
第二個表是 Marks,用來存儲基於年份的學生的標記。這里 SID 是 Student 表的外鍵。
1 CREATE TABLE Marks( 2 SID INT NOT NULL, 3 MARKS INT NOT NULL, 4 YEAR INT NOT NULL 5 );
讓我們直接使用 PlatformTransactionManager 來實現編程式方法從而實現事務。要開始一個新事務,你需要有一個帶有適當的 transaction 屬性的 TransactionDefinition 的實例。這個例子中,我們使用默認的 transaction 屬性簡單的創建了 DefaultTransactionDefinition 的一個實例。
當 TransactionDefinition 創建后,你可以通過調用 getTransaction() 方法來開始你的事務,該方法會返回 TransactionStatus 的一個實例。 TransactionStatus 對象幫助追蹤當前的事務狀態,並且最終,如果一切運行順利,你可以使用 PlatformTransactionManager 的 commit() 方法來提交這個事務,否則的話,你可以使用 rollback() 方法來回滾整個操作。
現在讓我們編寫我們的 Spring JDBC 應用程序,它能夠在 Student 和 Mark 表中實現簡單的操作。讓我們適當的使用 Eclipse IDE,並按照如下所示的步驟來創建一個 Spring 應用程序:
步驟一:創建一個名為 SpringExample 的項目,並在創建的項目中的 src 文件夾下創建包com.tutorialspoint。
步驟二:使用 Add JARs 選項添加必需的 Spring 庫。
步驟三:在項目中添加 Spring JDBC 指定的最新的庫 mysql-connector-java.jar,org.springframework.jdbc.jar 和 org.springframework.transaction.jar。如果沒有這些庫,你可以下載它們。
步驟四:創建 DAO 接口 StudentDAO 並列出所有需要的方法。盡管它不是必需的並且你可以直接編寫 StudentJDBCTemplate 類,但是作為一個好的實踐,我們還是做吧。
步驟五:在com.tutorialspoint包下創建其他必需的 Java 類 StudentMarks,StudentMarksMapper,StudentJDBCTemplate 和 MainApp。如果需要的話,你可以創建其他的 POJO 類。
步驟六:確保你已經在 TEST 數據庫中創建了 Student 和 Marks 表。還要確保你的 MySQL 服務器運行正常並且你使用給出的用戶名和密碼可以讀/寫訪問數據庫。
步驟七:在 src 文件夾下創建 Beans 配置文件 Beans.xml 。
最后一步:最后一步是創建所有 Java 文件和 Bean 配置文件的內容並按照如下所示的方法運行應用程序。
下面是數據訪問對象接口文件 StudentDAO.java 的內容:
1 package com.tutorialspoint; 2 import java.util.List; 3 import javax.sql.DataSource; 4 public interface StudentDAO { 5 /** 6 * This is the method to be used to initialize 7 * database resources ie. connection. 8 */ 9 public void setDataSource(DataSource ds); 10 /** 11 * This is the method to be used to create 12 * a record in the Student and Marks tables. 13 */ 14 public void create(String name, Integer age, Integer marks, Integer year); 15 /** 16 * This is the method to be used to list down 17 * all the records from the Student and Marks tables. 18 */ 19 public List<StudentMarks> listStudents(); 20 }
下面是 StudentMarks.java 文件的內容:
1 package com.tutorialspoint; 2 public class StudentMarks { 3 private Integer age; 4 private String name; 5 private Integer id; 6 private Integer marks; 7 private Integer year; 8 private Integer sid; 9 public void setAge(Integer age) { 10 this.age = age; 11 } 12 public Integer getAge() { 13 return age; 14 } 15 public void setName(String name) { 16 this.name = name; 17 } 18 public String getName() { 19 return name; 20 } 21 public void setId(Integer id) { 22 this.id = id; 23 } 24 public Integer getId() { 25 return id; 26 } 27 public void setMarks(Integer marks) { 28 this.marks = marks; 29 } 30 public Integer getMarks() { 31 return marks; 32 } 33 public void setYear(Integer year) { 34 this.year = year; 35 } 36 public Integer getYear() { 37 return year; 38 } 39 public void setSid(Integer sid) { 40 this.sid = sid; 41 } 42 public Integer getSid() { 43 return sid; 44 } 45 }
以下是 StudentMarksMapper.java 文件的內容:
1 package com.tutorialspoint; 2 import java.sql.ResultSet; 3 import java.sql.SQLException; 4 import org.springframework.jdbc.core.RowMapper; 5 public class StudentMarksMapper implements RowMapper<StudentMarks> { 6 public StudentMarks mapRow(ResultSet rs, int rowNum) throws SQLException { 7 StudentMarks studentMarks = new StudentMarks(); 8 studentMarks.setId(rs.getInt("id")); 9 studentMarks.setName(rs.getString("name")); 10 studentMarks.setAge(rs.getInt("age")); 11 studentMarks.setSid(rs.getInt("sid")); 12 studentMarks.setMarks(rs.getInt("marks")); 13 studentMarks.setYear(rs.getInt("year")); 14 return studentMarks; 15 } 16 }
下面是定義的 DAO 接口 StudentDAO 實現類文件 StudentJDBCTemplate.java:
1 package com.tutorialspoint; 2 import java.util.List; 3 import javax.sql.DataSource; 4 import org.springframework.dao.DataAccessException; 5 import org.springframework.jdbc.core.JdbcTemplate; 6 import org.springframework.transaction.PlatformTransactionManager; 7 import org.springframework.transaction.TransactionDefinition; 8 import org.springframework.transaction.TransactionStatus; 9 import org.springframework.transaction.support.DefaultTransactionDefinition; 10 public class StudentJDBCTemplate implements StudentDAO { 11 private DataSource dataSource; 12 private JdbcTemplate jdbcTemplateObject; 13 private PlatformTransactionManager transactionManager; 14 public void setDataSource(DataSource dataSource) { 15 this.dataSource = dataSource; 16 this.jdbcTemplateObject = new JdbcTemplate(dataSource); 17 } 18 public void setTransactionManager( 19 PlatformTransactionManager transactionManager) { 20 this.transactionManager = transactionManager; 21 } 22 public void create(String name, Integer age, Integer marks, Integer year){ 23 TransactionDefinition def = new DefaultTransactionDefinition(); 24 TransactionStatus status = transactionManager.getTransaction(def); 25 try { 26 String SQL1 = "insert into Student (name, age) values (?, ?)"; 27 jdbcTemplateObject.update( SQL1, name, age); 28 // Get the latest student id to be used in Marks table 29 String SQL2 = "select max(id) from Student"; 30 int sid = jdbcTemplateObject.queryForInt( SQL2 ); 31 String SQL3 = "insert into Marks(sid, marks, year) " + 32 "values (?, ?, ?)"; 33 jdbcTemplateObject.update( SQL3, sid, marks, year); 34 System.out.println("Created Name = " + name + ", Age = " + age); 35 transactionManager.commit(status); 36 } catch (DataAccessException e) { 37 System.out.println("Error in creating record, rolling back"); 38 transactionManager.rollback(status); 39 throw e; 40 } 41 return; 42 } 43 public List<StudentMarks> listStudents() { 44 String SQL = "select * from Student, Marks where Student.id=Marks.sid"; 45 List <StudentMarks> studentMarks = jdbcTemplateObject.query(SQL, 46 new StudentMarksMapper()); 47 return studentMarks; 48 } 49 }
現在讓我們改變主應用程序文件 MainApp.java,如下所示:
1 package com.tutorialspoint; 2 import java.util.List; 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 import com.tutorialspoint.StudentJDBCTemplate; 6 public class MainApp { 7 public static void main(String[] args) { 8 ApplicationContext context = 9 new ClassPathXmlApplicationContext("Beans.xml"); 10 StudentJDBCTemplate studentJDBCTemplate = 11 (StudentJDBCTemplate)context.getBean("studentJDBCTemplate"); 12 System.out.println("------Records creation--------" ); 13 studentJDBCTemplate.create("Zara", 11, 99, 2010); 14 studentJDBCTemplate.create("Nuha", 20, 97, 2010); 15 studentJDBCTemplate.create("Ayan", 25, 100, 2011); 16 System.out.println("------Listing all the records--------" ); 17 List<StudentMarks> studentMarks = studentJDBCTemplate.listStudents(); 18 for (StudentMarks record : studentMarks) { 19 System.out.print("ID : " + record.getId() ); 20 System.out.print(", Name : " + record.getName() ); 21 System.out.print(", Marks : " + record.getMarks()); 22 System.out.print(", Year : " + record.getYear()); 23 System.out.println(", Age : " + record.getAge()); 24 } 25 } 26 }
下面是配置文件 Beans.xml 的內容:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd "> 6 7 <!-- Initialization for data source --> 8 <bean id="dataSource" 9 class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 10 <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 11 <property name="url" value="jdbc:mysql://localhost:3306/TEST"/> 12 <property name="username" value="root"/> 13 <property name="password" value="password"/> 14 </bean> 15 16 <!-- Initialization for TransactionManager --> 17 <bean id="transactionManager" 18 class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 19 <property name="dataSource" ref="dataSource" /> 20 </bean> 21 22 <!-- Definition for studentJDBCTemplate bean --> 23 <bean id="studentJDBCTemplate" 24 class="com.tutorialspoint.StudentJDBCTemplate"> 25 <property name="dataSource" ref="dataSource" /> 26 <property name="transactionManager" ref="transactionManager" /> 27 </bean> 28 29 </beans>
當你完成了創建源和 bean 配置文件后,讓我們運行應用程序。如果你的應用程序運行順利的話,那么將會輸出如下所示的消息:
------Records creation-------- Created Name = Zara, Age = 11 Created Name = Nuha, Age = 20 Created Name = Ayan, Age = 25 ------Listing all the records-------- ID : 1, Name : Zara, Marks : 99, Year : 2010, Age : 11 ID : 2, Name : Nuha, Marks : 97, Year : 2010, Age : 20 ID : 3, Name : Ayan, Marks : 100, Year : 2011, Age : 25
Spring 聲明式事務管理
聲明式事務管理方法允許你在配置的幫助下而不是源代碼硬編程來管理事務。這意味着你可以將事務管理從事務代碼中隔離出來。你可以只使用注釋或基於配置的 XML 來管理事務。 bean 配置會指定事務型方法。這是與聲明式事務相關的步驟:
-
我們使用 標簽,它創建一個事務處理的建議,同時,我們定義一個匹配所有方法的切入點,我們希望這些方法是事務型的並且會引用事務型的建議。
-
如果在事務型配置中包含了一個方法的名稱,那么創建的建議在調用方法之前就會在事務中開始進行。
-
目標方法會在 try / catch 塊中執行。
- 如果方法正常結束,AOP 建議會成功的提交事務,否則它執行回滾操作。
讓我們看看上述步驟是如何實現的。但是在我們開始之前,至少有兩個數據庫表是至關重要的,在事務的幫助下,我們可以實現各種 CRUD 操作。以 Student 表為例,該表是使用下述 DDL 在 MySQL TEST 數據庫中創建的。
1 CREATE TABLE Student( 2 ID INT NOT NULL AUTO_INCREMENT, 3 NAME VARCHAR(20) NOT NULL, 4 AGE INT NOT NULL, 5 PRIMARY KEY (ID) 6 );
第二個表是 Marks,我們用來存儲基於年份的學生標記。在這里,SID 是 Student 表的外鍵。
1 CREATE TABLE Marks( 2 SID INT NOT NULL, 3 MARKS INT NOT NULL, 4 YEAR INT NOT NULL 5 );
現在讓我們編寫 Spring JDBC 應用程序來在 Student 和 Marks 表中實現簡單的操作。讓我們適當的使用 Eclipse IDE,並按照如下所示的步驟來創建一個 Spring 應用程序:
步驟一:創建一個名為 SpringExample 的項目,並在創建的項目中的 src 文件夾下創建包 com.tutorialspoint。
步驟二:使用 Add JARs 選項添加必需的 Spring 庫。
步驟三:在項目中添加其它必需的庫 mysql-connector-java.jar,org.springframework.jdbc.jar 和 org.springframework.transaction.jar。如果你還沒有這些庫,你可以下載它們。
步驟四:創建 DAO 接口 StudentDAO 並列出所有需要的方法。盡管它不是必需的並且你可以直接編寫 StudentJDBCTemplate 類,但是作為一個好的實踐,我們還是做吧。
步驟五:在 com.tutorialspoint 包下創建其他必需的 Java 類 StudentMarks,StudentMarksMapper,StudentJDBCTemplate 和 MainApp。如果需要的話,你可以創建其他的 POJO 類。
步驟六:確保你已經在 TEST 數據庫中創建了 Student 和 Marks 表。還要確保你的 MySQL 服務器運行正常並且你使用給出的用戶名和密碼可以讀/寫訪問數據庫。
步驟七:在 src 文件夾下創建 Beans 配置文件 Beans.xml 。
最后一步:最后一步是創建所有 Java 文件和 Bean 配置文件的內容並按照如下所示的方法運行應用程序。
下面是數據訪問對象接口文件 StudentDAO.java 的內容:
1 package com.tutorialspoint; 2 import java.util.List; 3 import javax.sql.DataSource; 4 public interface StudentDAO { 5 /** 6 * This is the method to be used to initialize 7 * database resources ie. connection. 8 */ 9 public void setDataSource(DataSource ds); 10 /** 11 * This is the method to be used to create 12 * a record in the Student and Marks tables. 13 */ 14 public void create(String name, Integer age, Integer marks, Integer year); 15 /** 16 * This is the method to be used to list down 17 * all the records from the Student and Marks tables. 18 */ 19 public List<StudentMarks> listStudents(); 20 }
以下是 StudentMarks.java 文件的內容:
1 package com.tutorialspoint; 2 public class StudentMarks { 3 private Integer age; 4 private String name; 5 private Integer id; 6 private Integer marks; 7 private Integer year; 8 private Integer sid; 9 public void setAge(Integer age) { 10 this.age = age; 11 } 12 public Integer getAge() { 13 return age; 14 } 15 public void setName(String name) { 16 this.name = name; 17 } 18 public String getName() { 19 return name; 20 } 21 public void setId(Integer id) { 22 this.id = id; 23 } 24 public Integer getId() { 25 return id; 26 } 27 public void setMarks(Integer marks) { 28 this.marks = marks; 29 } 30 public Integer getMarks() { 31 return marks; 32 } 33 public void setYear(Integer year) { 34 this.year = year; 35 } 36 public Integer getYear() { 37 return year; 38 } 39 public void setSid(Integer sid) { 40 this.sid = sid; 41 } 42 public Integer getSid() { 43 return sid; 44 } 45 }
下面是 StudentMarksMapper.java 文件的內容:
1 package com.tutorialspoint; 2 import java.sql.ResultSet; 3 import java.sql.SQLException; 4 import org.springframework.jdbc.core.RowMapper; 5 public class StudentMarksMapper implements RowMapper<StudentMarks> { 6 public StudentMarks mapRow(ResultSet rs, int rowNum) throws SQLException { 7 StudentMarks studentMarks = new StudentMarks(); 8 studentMarks.setId(rs.getInt("id")); 9 studentMarks.setName(rs.getString("name")); 10 studentMarks.setAge(rs.getInt("age")); 11 studentMarks.setSid(rs.getInt("sid")); 12 studentMarks.setMarks(rs.getInt("marks")); 13 studentMarks.setYear(rs.getInt("year")); 14 return studentMarks; 15 } 16 }
下面是定義的 DAO 接口 StudentDAO 實現類文件 StudentJDBCTemplate.java:
1 package com.tutorialspoint; 2 import java.util.List; 3 import javax.sql.DataSource; 4 import org.springframework.dao.DataAccessException; 5 import org.springframework.jdbc.core.JdbcTemplate; 6 public class StudentJDBCTemplate implements StudentDAO{ 7 private JdbcTemplate jdbcTemplateObject; 8 public void setDataSource(DataSource dataSource) { 9 this.jdbcTemplateObject = new JdbcTemplate(dataSource); 10 } 11 public void create(String name, Integer age, Integer marks, Integer year){ 12 try { 13 String SQL1 = "insert into Student (name, age) values (?, ?)"; 14 jdbcTemplateObject.update( SQL1, name, age); 15 // Get the latest student id to be used in Marks table 16 String SQL2 = "select max(id) from Student"; 17 int sid = jdbcTemplateObject.queryForInt( SQL2 ); 18 String SQL3 = "insert into Marks(sid, marks, year) " + 19 "values (?, ?, ?)"; 20 jdbcTemplateObject.update( SQL3, sid, marks, year); 21 System.out.println("Created Name = " + name + ", Age = " + age); 22 // to simulate the exception. 23 throw new RuntimeException("simulate Error condition") ; 24 } catch (DataAccessException e) { 25 System.out.println("Error in creating record, rolling back"); 26 throw e; 27 } 28 } 29 public List<StudentMarks> listStudents() { 30 String SQL = "select * from Student, Marks where Student.id=Marks.sid"; 31 List <StudentMarks> studentMarks=jdbcTemplateObject.query(SQL, 32 new StudentMarksMapper()); 33 return studentMarks; 34 } 35 }
現在讓我們改變主應用程序文件 MainApp.java,如下所示:
1 package com.tutorialspoint; 2 import java.util.List; 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 public class MainApp { 6 public static void main(String[] args) { 7 ApplicationContext context = 8 new ClassPathXmlApplicationContext("Beans.xml"); 9 StudentDAO studentJDBCTemplate = 10 (StudentDAO)context.getBean("studentJDBCTemplate"); 11 System.out.println("------Records creation--------" ); 12 studentJDBCTemplate.create("Zara", 11, 99, 2010); 13 studentJDBCTemplate.create("Nuha", 20, 97, 2010); 14 studentJDBCTemplate.create("Ayan", 25, 100, 2011); 15 System.out.println("------Listing all the records--------" ); 16 List<StudentMarks> studentMarks = studentJDBCTemplate.listStudents(); 17 for (StudentMarks record : studentMarks) { 18 System.out.print("ID : " + record.getId() ); 19 System.out.print(", Name : " + record.getName() ); 20 System.out.print(", Marks : " + record.getMarks()); 21 System.out.print(", Year : " + record.getYear()); 22 System.out.println(", Age : " + record.getAge()); 23 } 24 } 25 }
以下是配置文件 Beans.xml 的內容:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:tx="http://www.springframework.org/schema/tx" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 8 http://www.springframework.org/schema/tx 9 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 10 http://www.springframework.org/schema/aop 11 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 12 13 <!-- Initialization for data source --> 14 <bean id="dataSource" 15 class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 16 <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 17 <property name="url" value="jdbc:mysql://localhost:3306/TEST"/> 18 <property name="username" value="root"/> 19 <property name="password" value="cohondob"/> 20 </bean> 21 22 <tx:advice id="txAdvice" transaction-manager="transactionManager"> 23 <tx:attributes> 24 <tx:method name="create"/> 25 </tx:attributes> 26 </tx:advice> 27 28 <aop:config> 29 <aop:pointcut id="createOperation" 30 expression="execution(* com.tutorialspoint.StudentJDBCTemplate.create(..))"/> 31 <aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/> 32 </aop:config> 33 34 <!-- Initialization for TransactionManager --> 35 <bean id="transactionManager" 36 class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 37 <property name="dataSource" ref="dataSource" /> 38 </bean> 39 40 <!-- Definition for studentJDBCTemplate bean --> 41 <bean id="studentJDBCTemplate" 42 class="com.tutorialspoint.StudentJDBCTemplate"> 43 <property name="dataSource" ref="dataSource" /> 44 </bean> 45 46 </beans>
當你完成了創建源和 bean 配置文件后,讓我們運行應用程序。如果你的應用程序運行順利的話,那么會輸出如下所示的異常。在這種情況下,事務會回滾並且在數據庫表中不會創建任何記錄。
------Records creation-------- Created Name = Zara, Age = 11 Exception in thread "main" java.lang.RuntimeException: simulate Error condition
在刪除StudentJDBCTemplate類中create方法拋出異常的代碼后,你可以嘗試上述示例,在這種情況下,會提交事務並且你可以在數據庫中看見記錄。
注意:項目jar包如圖所示,其中也包含了Spring其它方面的一些jar包,小Alan偷一下懶就沒去剔除了,這一塊大家可以嘗試只留下必要的jar包,以便熟悉Spring所包含的每個jar包在項目中所能夠起到的作用,記得把jar包引入項目中才能夠運行上述的示例。
結束語:除了無可奈何地走向衰老,沒有人知道前面將會發生什么,沒有人。
可愛博主:AlanLee
博客地址:http://www.cnblogs.com/AlanLee
本文出自博客園,歡迎大家加入博客園。