本文只是簡單得實現一下事務的小例子,事務的具體內容,比如事務的等級,事務的具體實現原理等等。。。 菜鳥水平有限,暫時還更不了這個,以後的博客可能會涉及。 如果您看完本博客之後能簡單的實現一個事務,本文目的就達到了。
前兩天給公司的資料庫操作加了事務管理,今天博客就更一下這個吧。
先說明:本文只是簡單得實現一下事務,事務的具體內容,比如事務的等級,事務的具體實現原理等等。。。 菜鳥水平有限,暫時還更不了這個,以後的博客可能會涉及。
如果您看完本博客之後能簡單的實現一個事務,本文目的就達到了。
首先簡單通俗的解釋一下啥叫事務: 在一個方法里的所有操作資料庫的語句,要麼全部執行(方法沒有報錯),要麼全部不執行(方法拋錯,已經執行的語句回滾)。
xml形式實現事務,也是我在公司代碼中實現的事務。他的好處是不用對現有代碼進行任何修改,比較適合這種後期新加入的事務管理,缺點是可能會造成xml文件的龐大。
下麵是xml中各個信息:
<context:property-placeholder location="classpath:jdbc.properties" />
該語句用於讀取配置文件(資料庫的用戶名密碼等)
<aop:config proxy-target-class="true"></aop:config>
強制使用CGLIB代理(暫時不知道為啥,不加這句我的代碼會報錯)
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="defaultAutoCommit" value="true" /> <property name="driverClassName" value="${driverClassName}" /> <property name="url" value="${url}" /> <property name="username" value="umetrip" /> <property name="password" value="${password}" /> </bean>
數據源,不解釋!
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
註冊事務,並指定事務處理的數據源
<!-- 註冊資料庫操作類 -->
<bean id="testDao" class="testSpring.business.Dao.iface.impl.TestDaoImpl"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="dbTest1" class="testSpring.business.transaction.DbTest1"> <property name="testDao" ref="testDao" /> </bean> <aop:config> <aop:pointcut id="transactionPointcut" expression="execution(* testSpring.business.Dao.iface.impl..*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" /> </aop:config>
註冊事務的切入點。可以看到,事務是利用spring中的面向切麵,向方法中註入事務管理。
其中expression="execution(* testSpring.business.Dao.iface.impl..*.*(..)) :
1、execution(): 表達式主體。
2、第一個*號:表示返回類型,*號表示所有的類型。
3、包名:表示需要攔截的包名,後面的兩個句點表示當前包和當前包的所有子包,com.sample.service.impl包、子孫包下所有類的方法。
4、第二個*號:表示類名,*號表示所有的類。
5、*(..):最後這個星號表示方法名,*號表示所有的方法,後面括弧裡面表示方法的參數,兩個句點表示任何參數。
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 如果方法是以get開頭的方法,則不使用事務 --> <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED" /> <!-- 類中所有其他方法都使用事務管理 --> <tx:method name="*" /> </tx:attributes> </tx:advice>
為事務指定管理者並配置事務信息。
只需要配置xml文件即可,代碼不用做任何修改。
測試代碼:
//讀取配置文件(將配置文件中的bean載入進記憶體) ApplicationContext ctx = new ClassPathXmlApplicationContext("/testSpring/resources/applicationContext_transaction.xml"); //獲取的實例 DbTest1 bean = (DbTest1)ctx.getBean("dbTest1"); //調用方法 try{ bean.test(); }catch(Exception e){ e.printStackTrace(); }
TestDaoImpl類:
package testSpring.business.Dao.iface.impl; import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import testSpring.business.Dao.iface.ITestDao; import testSpring.business.bean.TableBean; /** * ITestDao.java : * @author xuejupo [email protected] * create in 2016-2-16 下午5:04:56 */ public class TestDaoImpl implements ITestDao{ private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource){ this.jdbcTemplate=new JdbcTemplate(dataSource); } @Override public void add(TableBean user) { // TODO Auto-generated method stub jdbcTemplate.update("insert into test values(?,?)", new Object[]{user.getId(),user.getName()}); this.del(1); jdbcTemplate.update("delete from test where id = ?",new Object[]{213123,2}); } @Override public void del(int id) { // TODO Auto-generated method stub jdbcTemplate.update("delete from test where id = ?",new Object[]{id}); } }
多次修改TestDaoImpl類的add代碼並執行結果發現:add方法如果拋出異常,那麼add方法內所有的sql語句都會回滾。但是如果add方法內沒有發生異常或者異常被處理,那麼add方法已經執行的sql語句就會被提交。
小結:
1.事務是針對某一個方法的,只要是在這個方法內拋錯,這個方法內的所有資料庫操作全部回滾(比如上面類中add方法里的del方法也會回滾)。
2.如果在進行事務管理的方法里將異常catch住並且寫入log,而沒有向外拋出,那麼當前方法事務無效。。。解決方法是可以在寫入log後向外拋出一個異常。
3.事務是很複雜的。。 不要看上面寫的很簡單。 比如事務的隔離等級,事務的鎖表等級(行鎖還是表鎖,還有是否鎖住索引等)。
PS:如果您看到的不是我的博客園的博客(爬蟲的僵屍博客),歡迎到我的博客跟我一起討論:http://www.cnblogs.com/xuejupo/