javascript
Spring学习总结三
Spring框架JdbcTemplate與事務
- Spring學習總結三
- 0、需要的jar包
- 1、JdbcTemplate模板
- 1.1、JdbcTemplateAPI的操作
- 1.1.1、User類
- 1.1.2、測試類
- 1.2、配置spring.xml實現操作數據庫的例子(采用DBCP數據源)
- 1.2.1、創建User實體類
- 1.2.2、創建UserDao類
- 1.2.3、配置spring.xml,將生產bean的任務交給spring容器
- 1.2.4、測試
- 1.3、配置spring.xml實現操作數據庫的例子(采用C3P0數據源)
- 1.3.1、創建User實體類
- 1.3.2、創建UserDao類
- 1.3.3、配置spring.xml
- 1.3.4、測試類
- 1.4、繼承JdbcDaoSupport的例子
- 1.4.1、實體類
- 1.4.2、UserDao類并繼承JdbcDaoSupport類
- 1.4.3、配置spring.xml
- 1.4.4、寫jdbc.properties配置文件
- 1.4.5、測試類
- 2、轉賬的例子,層層遞進
- 2.0、首先事務分級別
- 2.1、Read Uncommitted, Read commited, Repeatable read, Serializable
- 2.1.1、Read Uncommitted
- 2.1.1、Read Committed
- 2.1.1、Repeatable Read
- 2.1.1、Serializable
- 2.2、并發問題
- 2.2.1、臟讀
- 2.2.2、不可重復讀
- 2.2.3、幻讀
- 2.1、正常的一個轉賬(不存在事務)
- 2.1.1、創建AccountDao接口
- 2.1.2、創建實現類AccountDaoImp
- 2.1.3、創建AccountService接口
- 2.1.4、創建實現類AccountServiceImp
- 2.1.5、配置applicationContext.xml
- 2.1.6、測試
- 2.2、使用事務管理器+事務模板來處理事務
- 2.2.1、接口AccountDao
- 2.2.1、實現類AccountDaoImp
- 2.2.1、接口AccountService
- 2.2.1、實現類AccountServiceImp
- 2.2.1、applicationContext配置
- 2.2.1、測試
- 2.3、使用事務代理器來處理事務
- 2.3.1、創建2個接口
- 2.3.2、創建2個實現類
- 2.3.3、編寫applicationContext.xml
- 2.3.4、測試
- 2.4、使用AOP來處理事務
- 2.4.1、2個接口
- 2.4.2、2個實現類
- 2.4.3、編寫applicationContext.xml(重頭戲)
- 2.4.4、測試
- 2.5、使用注解來處理事務
- 2.5.1、2個接口
- 2.5.2、2個實現類
- 2.5.3、配置applicationContext.xml
- 2.5.4、測試
- 至此,spring除了整合沒有說以外,其他的都寫的差不多了!
- 參考
Spring學習總結三
今天主要說下面幾個點:
0、需要的jar包
下面的包太多了,就不幫大家找了哈!一般這樣百度mchange.c3p0 commons.dbcp commons.logging就可以找到對應的jar,spring的話直接百度Spring下載地址就行了
1、JdbcTemplate模板
說到JdbcTemplate模板,其實我也沒學過!我只學過Hibernate的模板。不過都是數據庫,大體操作類似!
1.1、JdbcTemplateAPI的操作
大概需要下面幾個步驟:
1.1.1、User類
package com.csa.entity;public class User {private String username;private String phone;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User [username=" + username + ", phone=" + phone + ", password=" + password + "]";} }1.1.2、測試類
package com.csa.main;import java.util.List; import org.apache.commons.dbcp.BasicDataSource; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import com.csa.entity.User; public class JdbcTemplateAPI {public static void main(String[] args) {// 1.創建數據源(連接池)dhcpBasicDataSource dataSource = new BasicDataSource();// * 基本4項dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:自己數據庫的端口號/自己的數據庫");dataSource.setUsername("自己的用戶名");dataSource.setPassword("自己的密碼");// 2.創建模板,JdbcTemplate需要一個數據源,這里是基本的數據源JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);// 3.通過api操作@SuppressWarnings({ "unchecked", "rawtypes" })List<User> queryForList = jdbcTemplate.query("select * from User",new BeanPropertyRowMapper(User.class));for (User user : queryForList) {System.out.println(user);}} }測試結果:根據大家數據庫的不同,數據結果自然不一樣!
1.2、配置spring.xml實現操作數據庫的例子(采用DBCP數據源)
從上面的例子我們可以看出,dataSource和jdbcTemplate可以交由給spring容器來做!
于是接下來我們將把生成bean的任務交給spring容器,實驗需要做的幾步:
1.2.1、創建User實體類
同上!
1.2.2、創建UserDao類
下面采用的是依賴注入的思想。
package com.csa.dao; import java.util.List; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import com.csa.entity.User;public class UserDao {private JdbcTemplate jdbcTemplate;public JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@SuppressWarnings({ "rawtypes", "unchecked" })public List<User> list(){return jdbcTemplate.query("select * from User", new BeanPropertyRowMapper(User.class));} }1.2.3、配置spring.xml,將生產bean的任務交給spring容器
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 數據源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:端口/數據庫名"></property><property name="username" value="用戶名"></property><property name="password" value="密碼"></property></bean><!-- jdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- Dao --><bean id="userDao" class="com.csa.dao.UserDao"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean></beans>1.2.4、測試
import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.dao.UserDao; import com.csa.entity.User;public class TestDBCP {public static void main(String[] args) {String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserDao userDao = (UserDao) applicationContext.getBean("userDao");List<User> list = userDao.list();for (User user : list) {System.out.println(user);}} }1.3、配置spring.xml實現操作數據庫的例子(采用C3P0數據源)
我們現在采用的數據源是基本的數據源,于是我們可以改變一下數據源。改為C3P0數據源!
同樣我們把生成bean的任務交給spring容器,實驗需要做的幾步:
1.3.1、創建User實體類
同上!
1.3.2、創建UserDao類
同上!使用依賴注入的思想!
1.3.3、配置spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 這里要注意,BasicDataSource類的屬性名與C3P0的屬性名有點不同!大家寫的時候別忽略了! --><!-- 數據源 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:端口/數據庫名"></property><property name="user" value="用戶名"></property><property name="password" value="密碼"></property></bean><!-- jdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- Dao --><bean id="userDao" class="com.csa.dao.UserDao"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean></beans>1.3.4、測試類
import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.dao.UserDao; import com.csa.entity.User; public class TestC3P0 {public static void main(String[] args) {String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserDao userDao = (UserDao) applicationContext.getBean("userDao");List<User> list = userDao.list();for (User user : list) {System.out.println(user);}} }1.4、繼承JdbcDaoSupport的例子
我們從上面的DBCP和C3P0的例子中可以看到,我們在Dao里面總要寫一個JdbcTemplate模板!很麻煩,這種事情應該交給框架來做。
于是要做下面幾個步驟:
1.4.1、實體類
同上!
1.4.2、UserDao類并繼承JdbcDaoSupport類
package com.csa.dao; import java.util.List; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.support.JdbcDaoSupport; import com.csa.entity.User; // 這樣簡潔多了! public class UserDao extends JdbcDaoSupport {@SuppressWarnings({ "rawtypes", "unchecked" })public List<User> list(){return this.getJdbcTemplate().query("select * from User", new BeanPropertyRowMapper(User.class));} }1.4.3、配置spring.xml
我們發現spring.xml的配置也變得非常簡潔了!
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 加載jdbc配置文件 --><context:property-placeholder location="classpath:config/jdbc.properties"/><!-- 數據源 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><!-- 下面的有點像EL表達式 --><property name="driverClass" value="${jdbc.driverClass}"></property><property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- Dao --><bean id="userDao" class="com.csa.dao.UserDao"><property name="dataSource" ref="dataSource"></property></bean></beans>1.4.4、寫jdbc.properties配置文件
我們看到了在spring.xml中有一個元素是<context:property-placeholder location="classpath:config/jdbc.properties"/>。
這個我們要在src/config/下創建一個jdbc.properties配置文件!內容如下:
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql://localhost:端口/數據庫名 jdbc.user=用戶名 jdbc.password=密碼1.4.5、測試類
import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.dao.UserDao; import com.csa.entity.User;public class TestSupport {public static void main(String[] args) {String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserDao userDao = (UserDao) applicationContext.getBean("userDao");List<User> list = userDao.list();for (User user : list) {System.out.println(user);}} }2、轉賬的例子,層層遞進
要說事務,首先是事務具有 原子性、一致性、隔離性、持久性 ,而轉賬的例子可以說是非常經典了。
需要的jar(多了AOP):
2.0、首先事務分級別
在mysql的默認隔離級別是4,而oracle默認隔離級別是2。
2.1、Read Uncommitted, Read commited, Repeatable read, Serializable
2.1.1、Read Uncommitted
最低的隔離級別,Read Uncommitted最直接的效果就是一個事務可以讀取另一個事務并未提交的更新結果。
2.1.1、Read Committed
Read Committed通常是大部分數據庫采用的默認隔離級別,它在Read Uncommitted隔離級別基礎上所做的限定更進一步, 在該隔離級別下,一個事務的更新操作結果只有在該事務提交之后,另一個事務才可能讀取到同一筆數據更新后的結果。 所以,Read Committed可以避免Read Uncommitted隔離級別下存在的臟讀問題, 但,無法避免不可重復讀取和幻讀的問題。
2.1.1、Repeatable Read
Repeatable Read隔離級別可以保證在整個事務的過程中,對同一筆數據的讀取結果是相同的,不管其他事務是否同時在對同一筆數據進行更新,也不管其他事務對同一筆數據的更新提交與否。 Repeatable Read隔離級別避免了臟讀和不可重復讀取的問題,但無法避免幻讀。(mysql默認隔離級別)
2.1.1、Serializable
最為嚴格的隔離級別,所有的事務操作都必須依次順序執行,可以避免其他隔離級別遇到的所有問題,是最為安全的隔離級別, 但同時也是性能最差的隔離級別,因為所有的事務在該隔離級別下都需要依次順序執行,所以,并發度下降,吞吐量上不去,性能自然就下來了。 因為該隔離級別極大的影響系統性能,所以,很少場景會使用它。通常情況下,我們會使用其他隔離級別加上相應的并發鎖的機制來控制對數據的訪問,這樣既保證了系統性能不會損失太大,也能夠一定程度上保證數據的一致性。
2.2、并發問題
2.2.1、臟讀
針對未提交數據如果一個事務中對數據進行了更新,但事務還沒有提交,另一個事務可以“看到”該事務沒有提交的更新結果,這樣造成的問題就是,如果第一個事務回滾,那么,第二個事務在此之前所“看到”的數據就是一筆臟數據。
2.2.2、不可重復讀
針對其他提交前后,讀取數據本身的對比不可重復讀取是指同一個事務在整個事務過程中對同一筆數據進行讀取,每次讀取結果都不同。如果事務1在事務2的更新操作之前讀取一次數據,在事務2的更新操作之后再讀取同一筆數據一次,兩次結果是不同的,所以,Read Uncommitted也無法避免不可重復讀取的問題。
2.2.3、幻讀
針對其他提交前后,讀取數據條數的對比 幻讀是指同樣一筆查詢在整個事務過程中多次執行后,查詢所得的結果集是不一樣的?;米x針對的是多筆記錄。在Read Uncommitted隔離級別下, 不管事務2的插入操作是否提交,事務1在插入操作之前和之后執行相同的查詢,取得的結果集是不同的,所以,Read Uncommitted同樣無法避免幻讀的問題。
2.1、正常的一個轉賬(不存在事務)
說完事務,接下來我們來做一個關于轉賬,然后不存在事務的情況會發生什么?
需要的幾個步驟:
2.1.1、創建AccountDao接口
package com.csa.dao; public interface AccountDao {/*** 出賬* @param outer* @param money*/public void out(String outer, Integer money);/*** 入賬* @param inter* @param money*/public void in(String inner, Integer money); }2.1.2、創建實現類AccountDaoImp
package com.csa.dao.imp;import org.springframework.jdbc.core.support.JdbcDaoSupport;import com.csa.dao.AccountDao;public class AccountDaoImp extends JdbcDaoSupport implements AccountDao {@Overridepublic void out(String outer, Integer money) {this.getJdbcTemplate().update("update account set money = money - ? where username = ?", money, outer);}@Overridepublic void in(String inner, Integer money) {this.getJdbcTemplate().update("update account set money = money + ? where username = ?", money, inner);}}2.1.3、創建AccountService接口
package com.csa.service; public interface AccountService {/*** 轉賬* @param outer 出賬人* @param inner 入賬人* @param money 金錢*/public void transfer(String outer, String inner, int money); }2.1.4、創建實現類AccountServiceImp
package com.csa.service.imp; import com.csa.dao.AccountDao; import com.csa.service.AccountService;public class AccountServiceImp implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}@Overridepublic void transfer(String outer, String inner, int money) {accountDao.out(outer, money);// 如果將下面的語句放開,程序執行后將報錯,并且出賬人會減1000大洋,而入賬人并沒有增加1000大洋// int i = 1/0;accountDao.in(inner, money);}}2.1.5、配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- dataSource --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><!-- 我這里采用的數據庫名是transferAccounts其中有一個表:Account表,存儲每個人的"大洋"信息!--><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/transferAccounts"></property><property name="user" value="用戶名"></property><property name="password" value="密碼"></property></bean><!-- dao --><bean id="accountDao" class="com.csa.dao.imp.AccountDaoImp"><property name="dataSource" ref="dataSource"></property></bean><!-- service --><bean id="accountService" class="com.csa.service.imp.AccountServiceImp"><property name="accountDao" ref="accountDao"></property></bean></beans>2.1.6、測試
package com.csa.app;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.service.AccountService;public class App {public static void main(String[] args) {String xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);AccountService accountService = (AccountService) applicationContext.getBean("accountService");// 數據庫中有jack和rose這兩個條目!accountService.transfer("jack","rose",1000);} }2.2、使用事務管理器+事務模板來處理事務
我們發現,如果上面**出現除零異常后,在我們轉賬的邏輯上出現了異常,這1000大洋不翼而飛(入我們的口袋了)!**這不是我們想要的結果。那該怎么辦呢?
spring處理事務的其中一種,它的操作如下:
這個例子的幾個步驟:
2.2.1、接口AccountDao
與上面的一樣!
2.2.1、實現類AccountDaoImp
與上面的一樣!
2.2.1、接口AccountService
與上面的一樣!
2.2.1、實現類AccountServiceImp
需要注入一個TransactionTemplate,事務模板調用execute方法。
package com.csa.service.imp;import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate;import com.csa.dao.AccountDao; import com.csa.service.AccountService;public class AccountServiceImp implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}private TransactionTemplate transactionTemplate;public void setTransactionTemplate(TransactionTemplate transactionTemplate) {this.transactionTemplate = transactionTemplate;}@Overridepublic void transfer(String outer, String inner, int money) {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {accountDao.out(outer, money);int i = 1/0;accountDao.in(inner, money);}});} }2.2.1、applicationContext配置
需要配置事務管理器和事務模板,并且將事務模板注入到Serveice中。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- dataSource --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/transferAccounts"></property><property name="user" value="用戶名"></property><property name="password" value="密碼"></property></bean><!-- dao --><bean id="accountDao" class="com.csa.dao.imp.AccountDaoImp"><property name="dataSource" ref="dataSource"></property></bean><!-- service --><bean id="accountService" class="com.csa.service.imp.AccountServiceImp"><property name="accountDao" ref="accountDao"></property><property name="transactionTemplate" ref="transactionTemplate"></property></bean><!-- transactionManager管理器 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- transactionTemplate模板 --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="txManager"></property></bean></beans>2.2.1、測試
package com.csa.app; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.service.AccountService;public class App {public static void main(String[] args) {String xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);AccountService accountService = (AccountService) applicationContext.getBean("accountService");accountService.transfer("jack","rose",1000);} }2.3、使用事務代理器來處理事務
使用事務代理來處理事務需要以下幾個步驟:
我們的例子需要做下面幾個步驟:
2.3.1、創建2個接口
兩個接口都未改變!
2.3.2、創建2個實現類
UserDao沒變,UserService改變為第一個版本!
package com.csa.service.imp; import com.csa.dao.AccountDao; import com.csa.service.AccountService;public class AccountServiceImp implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}@Overridepublic void transfer(String outer, String inner, int money) {accountDao.out(outer, money);// int i = 1/0;accountDao.in(inner, money);}}2.3.3、編寫applicationContext.xml
需要配置事務管理器,事務代理,然后再事務代理中注入兩個屬性,分別是事務管理器和事務屬性。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- dataSource --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/transferAccounts"></property><property name="user" value="用戶名"></property><property name="password" value="密碼"></property></bean><!-- dao --><bean id="accountDao" class="com.csa.dao.imp.AccountDaoImp"><property name="dataSource" ref="dataSource"></property></bean><!-- service --><bean id="accountService" class="com.csa.service.imp.AccountServiceImp"><property name="accountDao" ref="accountDao"></property></bean><!-- transactionManager管理器 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 4 service 代理對象 4.1 proxyInterfaces 接口 4.2 target 目標類4.3 transactionManager 事務管理器4.4 transactionAttributes 事務屬性(事務詳情)prop.key :確定哪些方法使用當前事務配置prop.text:用于配置事務詳情格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception傳播行為 隔離級別 是否只讀 異?;貪L 異常提交例如:<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop> 默認傳播行為,和隔離級別<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly</prop> 只讀<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,+java.lang.ArithmeticException</prop> 有異常扔提交--><bean id="proxyAccountService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="proxyInterfaces" value="com.csa.service.AccountService"></property><property name="target" ref="accountService"></property><!-- 事務管理器 --><property name="transactionManager" ref="txManager"></property><!-- 事務屬性 --><property name="transactionAttributes"><props><prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop></props></property></bean></beans>2.3.4、測試
package com.csa.app; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.service.AccountService;public class App {public static void main(String[] args) {String xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);AccountService accountService = (AccountService) applicationContext.getBean("proxyAccountService");accountService.transfer("jack","rose",1000);} }2.4、使用AOP來處理事務
AOP來處理事務需要做的事情:
我們要做的事情:
2.4.1、2個接口
沒變!
2.4.2、2個實現類
沒變!
2.4.3、編寫applicationContext.xml(重頭戲)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- dataSource --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/transferAccounts"></property><property name="user" value="用戶名"></property><property name="password" value="密碼"></property></bean><!-- dao --><bean id="accountDao" class="com.csa.dao.imp.AccountDaoImp"><property name="dataSource" ref="dataSource"></property></bean><!-- service --><bean id="accountService" class="com.csa.service.imp.AccountServiceImp"><property name="accountDao" ref="accountDao"></property></bean><!-- 1.事務管理器 --><!-- transactionManager管理器 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 2.事務詳情(事務通知) , 在aop篩選基礎上,對ABC三個確定使用什么樣的事務。例如:AC讀寫、B只讀 等<tx:attributes> 用于配置事務詳情(屬性屬性)<tx:method name=""/> 詳情具體配置propagation 傳播行為 , REQUIRED:必須;REQUIRES_NEW:必須是新的isolation 隔離級別--><tx:advice id="txAdvisor" transaction-manager="txManager"><tx:attributes><tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/></tx:attributes></tx:advice><!-- 3.AOP編程,目標類有ABCD(4個連接點),切入點表達式 確定增強的連接器,從而獲得切入點:ABC --><aop:config><aop:advisor advice-ref="txAdvisor" pointcut="execution(* com.csa.service..*.*(..))"/></aop:config></beans>2.4.4、測試
package com.csa.app; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.service.AccountService;public class App {public static void main(String[] args) {String xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);AccountService accountService = (AccountService) applicationContext.getBean("accountService");accountService.transfer("jack","rose",1000);} }2.5、使用注解來處理事務
用注解來處理事務:
我們需要做的事情:
2.5.1、2個接口
與上面的一樣,沒變!
2.5.2、2個實現類
UserDao沒變,UserService添加了注解。
package com.csa.service.imp; import org.springframework.transaction.annotation.Transactional; import com.csa.dao.AccountDao; import com.csa.service.AccountService;// 在類上面加的話,是作用于這個類的所有方法 @Transactional public class AccountServiceImp implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}// 在方法上面加的話只作用于這個方法。// @Transactional@Overridepublic void transfer(String outer, String inner, int money) {accountDao.out(outer, money);int i = 1/0;accountDao.in(inner, money);}}2.5.3、配置applicationContext.xml
主要編寫一個注解驅動(掃描器)!
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- dataSource --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/transferAccounts"></property><property name="user" value="root"></property><property name="password" value="3306"></property></bean><!-- dao --><bean id="accountDao" class="com.csa.dao.imp.AccountDaoImp"><property name="dataSource" ref="dataSource"></property></bean><!-- service --><bean id="accountService" class="com.csa.service.imp.AccountServiceImp"><property name="accountDao" ref="accountDao"></property></bean><!-- transactionManager管理器 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 注解驅動 --><tx:annotation-driven transaction-manager="txManager"/></beans>2.5.4、測試
package com.csa.app;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.service.AccountService;public class App {public static void main(String[] args) {String xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);AccountService accountService = (AccountService) applicationContext.getBean("accountService");accountService.transfer("jack","rose",1000);} }至此,spring除了整合沒有說以外,其他的都寫的差不多了!
參考
各種博客,各種百度,各種以前的案例,黑馬的筆記等!鏈接太多!
總結
以上是生活随笔為你收集整理的Spring学习总结三的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring学习总结二
- 下一篇: HR面试看重这些点