Spring封裝了事務管理的程式碼
事務的操作一般有三種:
- 開啟事務
- 提交事務
- 回滾事務
Spring中管理事務的物件
因為在不同平臺,操作事務的程式碼各不相同,spring提供了一個介面.
PlatfromTransactionManager介面
在開發中都是直接使用它的實現類,常用的實現類有如下:
- DataSourceTransactionManager 使用jdbc或者mybatis進行資料持久化時使用
- HiberanteTransactionManager ==使用hibernate進行資料持久化時使用==
TransactionDefinition
它是一個介面,是定義事務的資訊物件,提供瞭如下常用的方法:
TransactionStatus
它是一個介面,提供了事務具體的執行狀態,描述了某一個時間點上事務物件的狀態資訊。提供瞭如下常用的方法:
==注意:在spring中使用事務,最為核心的物件就是TransactionManager物件==
==記得在spring配置檔案中必須配置TranscationManager==
Spring管理事務的屬性介紹
- 事務的隔離級別
-
- 讀未提交
-
- 讀已提交
-
- 可重複讀
-
- 序列化
- 是否只讀
- true 只讀
- false 可操作
- 事務的傳播行為
保證同一個事務中
屬性 | 含義 |
---|---|
PROPAGATION_REQUIRED | 支援當前事務,如果不存在 就新建一個(預設) |
PROPAGATION_SUPPORTS | 支援當前事務,如果不存在,就不使用事務 |
PROPAGATION_MANDATORY | 支援當前事務,如果不存在,丟擲異常 |
保證沒有在同一個事務中
屬性 | 含義 |
---|---|
PROPAGATION_REQUIRES_NEW | 如果有事務存在,掛起當前事務,建立一個新的事務 |
PROPAGATION_NOT_SUPPORTED | 以非事務方式執行,如果有事務存在,掛起當前事務 |
PROPAGATION_NEVER | 以非事務方式執行,如果有事務存在,丟擲異常 |
PROPAGATION_NESTED | 如果當前事務存在,則巢狀事務執行 |
超過時間
以秒為單位進行設定。如果設定為-1(預設值),表示沒有超時限制.
no-rollback-for:指定產生某個異常時,不回滾。產生其他異常時回滾。沒有預設值,任何異常都回滾
rollback-for:指定產生某個異常時,回滾。產生其他異常時不回滾。沒有預設值,任何異常都回滾
Spring管理事務方式
1. 編碼式
步驟
- 將核心事務管理器配置到spring的容器中
//核心事務管理器是依賴於資料來源的
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
複製程式碼
- 配置事務管理模板TransactionTemplate
<!-- 事務模板 -->
<bean name="Template" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
複製程式碼
- 將事務模板注入到Service中
<bean name="AccountService" class="madness.service.AccountServiceImpl">
<property name="dao" ref="AccountDao"></property>
<property name="template" ref="Template"></property>
</bean>
複製程式碼
- 在Service中呼叫模板
注意:在模板中,已經實現了開啟事務,提交事務,回滾事務的方法.
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate template;
@Override
public void tranfer(Integer from, Integer to, String money) {
template.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
dao.takeMoney(from, money);
//int i = 100/0;
dao.saveMoney(to, money);
}
});
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
public void setTemplate(TransactionTemplate template) {
this.template = template;
}
}
複製程式碼
2. xml配置
- 導包
- 匯入約束
- spring壓縮包中的schema資料夾中的tx資料夾
- 配置通知
<!-- config TransactionManagerAdvice -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="tranfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
複製程式碼
- 注意:這裡的tx:method中的name屬性是根據我們的方法來找的.如果我們每次的方法名都不一樣,每次都要進行配置.為了避免重複,我們可以將方法名規定好
- 將通知織入目標物件
<aop:config>
<aop:pointcut expression="execution( * madness.service.*ServiceImpl.*(..))" id="txPc"/>
<!--
配置切面:通知+切點
advice-ref:通知的名稱
pointcut-ref:切點的名稱
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
複製程式碼
3. 註解配置
- 導包
- 匯入約束
- 開始註解配置事務
<tx:annotation-driven/>
@EnableTransactionManagement註解:啟用spring註解事務支援
複製程式碼
- 使用註解配置事務
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
複製程式碼
- ==如果方法太多我們可以將註解配置在類上.==
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
public class AccountServiceImpl implements AccountService {
複製程式碼
- ==如果其中有方法的註解配置不一樣,我們可以在該方法上另外使用註解進行配置==
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=true)
public void tranfer(Integer from, Integer to, String money) {
dao.takeMoney(from, money);
//int i = 100/0;
dao.saveMoney(to, money);
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
複製程式碼
4. 純註解配置
不使用applicationContext.xml檔案,使用配置類來達到純註解配置spring
- 主配置類
@Configuration
@ComponentScan("com.itheima")
@Import(value = { DaoConfig.class, TransactionConfig.class })
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
public class SpringConfig {
}
複製程式碼
- Dao配置類(資料來源與jdbcTemplate模板)
public class DaoConfig {
@Value("${jdbc.driverClass}")
private String driverClass;
@Value("${jdbc.jdbcUrl}")
private String url;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource")
public DataSource getDataSource(){
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass(driverClass);
ds.setJdbcUrl(url);
ds.setUser(user);
ds.setPassword(password);
} catch (Exception e) {
e.printStackTrace();
}
return ds;
}
@Bean("jdbcTemplate")
public JdbcTemplate getJdbcTemplate(@Qualifier("dataSource") DataSource dataSource){
JdbcTemplate jt = new JdbcTemplate(dataSource);
return jt;
}
}
複製程式碼
- 事務管理器配置類
public class TransactionConfig {
@Bean("transactionManager")
public PlatformTransactionManager getTranscationManager(@Qualifier("dataSource") DataSource dataSource){
DataSourceTransactionManager dt = new DataSourceTransactionManager(dataSource);
return dt;
}
}
複製程式碼