由於我們操作數據庫的時候可能會遇到相對應的異常,導致我們數據庫操作進行到一半,便停止,出現髒數據。所以這裏需要用到事務防止出現這種情況。關於註解的配置主要分爲兩類。一類是註解式事務,一類是xml聲明式事務。相對來說,註解式事務配置較爲簡單,代碼量較少,應用也較爲廣泛,所以這裏主要介紹註解式事務的配置。不過首先先介紹下手動回滾事務。
一、 手動回滾事務
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
PlatformTransactionManager txManager = ContextLoader.getCurrentWebApplicationContext().getBean(PlatformTransactionManager.class);
TransactionStatus status = txManager.getTransaction(def);
try {
cardService.add();
int x=1/0;
txManager.commit(status);// 事務提交
} catch (Exception e) {
e.printStackTrace();
txManager.rollback(status);// 事務回滾
}
二、 註解式相關配置使用
- xml配置
<!-- ***********************事務配置************************** -->
<bean id="dataSourceForFact" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl" />
<property name="user" value="scott" />
<property name="password" value="oracle" />
<property name="acquireIncrement" value="3" />
<property name="initialPoolSize" value="3" />
<property name="minPoolSize" value="2" />
<property name="maxPoolSize" value="75" />
<property name="maxIdleTime" value="600" />
<property name="idleConnectionTestPeriod" value="900" />
<property name="maxStatements" value="100" />
<property name="numHelperThreads" value="10" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!-- 集成hibernate.cfg.xml -->
<property name="dataSource" ref="dataSourceForFact" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<!-- 集成hbm.xml -->
<property name="packagesToScan" value="ffcs.cn" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
- 方法調用
爲了方便,我直接將註解放在類名上面,這樣子這個類的所有方法都默認調用這個註解
@Transactional(rollbackFor = Exception.class)
public class CardController {}
三、 注意點
-
一般事務的使用是在業務邏輯層。這樣子調用一個dao發生錯誤,即可回滾之前所調用的dao方法。 如何辨別哪一塊代碼層是業務邏輯層,只需要觀察哪一塊代碼層能夠實行多個數據庫操作。比如service層一個方法調用了多個dao即可認爲是業務邏輯層。亦或是一個service調用一個dao方法,而一個controller調用了多個sevice,則controller層即爲業務邏輯層。
-
一開始只使用@Transactional註解時候,設置1/0這種運行時異常,事務能夠正常回滾。但是遇到非運行時異常,卻發現sql操作不能回滾,這又是咋回事。俺不懂,查閱資料後,發現對於非運行時異常,我們需要添加配置(rollbackFor = Exception.class)才能夠回滾,當然你也可以使用TransactionAspectSupport.currentTransactionStatus()
.setRollbackOnly();來手動回滾,如下
try {
cardService.add();
throw new RuntimeException("Rollback");
} catch (Exception e) {
// 回滾操作
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
System.out.println("出錯了");
}