Spring-AOP事務

JasonTam發表於2018-08-16

Spring封裝了事務管理的程式碼

事務的操作一般有三種:

  1. 開啟事務
  2. 提交事務
  3. 回滾事務
Spring中管理事務的物件

因為在不同平臺,操作事務的程式碼各不相同,spring提供了一個介面.

PlatfromTransactionManager介面

image

在開發中都是直接使用它的實現類,常用的實現類有如下:

image

  • DataSourceTransactionManager 使用jdbc或者mybatis進行資料持久化時使用
  • HiberanteTransactionManager ==使用hibernate進行資料持久化時使用==
TransactionDefinition

它是一個介面,是定義事務的資訊物件,提供瞭如下常用的方法:

image

TransactionStatus

它是一個介面,提供了事務具體的執行狀態,描述了某一個時間點上事務物件的狀態資訊。提供瞭如下常用的方法:

image

==注意:在spring中使用事務,最為核心的物件就是TransactionManager物件==

==記得在spring配置檔案中必須配置TranscationManager==

Spring管理事務的屬性介紹
  1. 事務的隔離級別
    1. 讀未提交
    1. 讀已提交
    1. 可重複讀
    1. 序列化
  1. 是否只讀
  • true 只讀
  • false 可操作
  1. 事務的傳播行為
保證同一個事務中
屬性 含義
PROPAGATION_REQUIRED 支援當前事務,如果不存在 就新建一個(預設)
PROPAGATION_SUPPORTS 支援當前事務,如果不存在,就不使用事務
PROPAGATION_MANDATORY 支援當前事務,如果不存在,丟擲異常
保證沒有在同一個事務中
屬性 含義
PROPAGATION_REQUIRES_NEW 如果有事務存在,掛起當前事務,建立一個新的事務
PROPAGATION_NOT_SUPPORTED 以非事務方式執行,如果有事務存在,掛起當前事務
PROPAGATION_NEVER 以非事務方式執行,如果有事務存在,丟擲異常
PROPAGATION_NESTED 如果當前事務存在,則巢狀事務執行
超過時間

以秒為單位進行設定。如果設定為-1(預設值),表示沒有超時限制.

no-rollback-for:指定產生某個異常時,不回滾。產生其他異常時回滾。沒有預設值,任何異常都回滾
rollback-for:指定產生某個異常時,回滾。產生其他異常時不回滾。沒有預設值,任何異常都回滾

Spring管理事務方式

1. 編碼式
步驟
  1. 將核心事務管理器配置到spring的容器中
  //核心事務管理器是依賴於資料來源的
 <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource"></property>     
     </bean>
複製程式碼
  1. 配置事務管理模板TransactionTemplate
  <!-- 事務模板 -->
     <bean name="Template" class="org.springframework.transaction.support.TransactionTemplate">
          <property name="transactionManager" ref="transactionManager"></property>
     </bean>
複製程式碼
  1. 將事務模板注入到Service中
 <bean name="AccountService" class="madness.service.AccountServiceImpl">
        <property name="dao" ref="AccountDao"></property>
        <property name="template" ref="Template"></property>
    </bean>
複製程式碼
  1. 在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配置
  1. 導包
  2. 匯入約束
  • spring壓縮包中的schema資料夾中的tx資料夾
  1. 配置通知
<!-- 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屬性是根據我們的方法來找的.如果我們每次的方法名都不一樣,每次都要進行配置.為了避免重複,我們可以將方法名規定好

image

  1. 將通知織入目標物件
 <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. 註解配置
  1. 導包
  2. 匯入約束
  3. 開始註解配置事務
 <tx:annotation-driven/>
 
 @EnableTransactionManagement註解:啟用spring註解事務支援
複製程式碼
  1. 使用註解配置事務
 @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

  1. 主配置類
 @Configuration
@ComponentScan("com.itheima")
@Import(value = { DaoConfig.class, TransactionConfig.class })
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
public class SpringConfig {

}
複製程式碼
  1. 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;
}
}
複製程式碼
  1. 事務管理器配置類
public class TransactionConfig {

@Bean("transactionManager")
public PlatformTransactionManager getTranscationManager(@Qualifier("dataSource") DataSource dataSource){

DataSourceTransactionManager dt = new DataSourceTransactionManager(dataSource);

return dt;
}
}
複製程式碼

相關文章