開始懷疑Spring框架的jdbc事務處理方式

lemon_zc1949發表於2005-09-28
目前我做了個小小的試驗,證明了Spring的jdbc事務的問題。我的環境:
使用jakarta commons dbcp 的 org.apache.commons.dbcp.BasicDataSource,作為DataSource.
xml中的配置如下:

    <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost/TransactionTest" />
        <property name="username" value="zc" />
        <property name="password" value="zc" />
        <property name="defaultAutoCommit" value="false" />
    </bean>
<p class="indent">


my sql 資料庫TransactionTest中有2個表,一個account, 一個accountprofile,分別弄了2個dao

    <bean id="accountdao"
          class="test.AccountDaoImp" >
          <property name="dataSource" ref="datasource" />
    </bean>
    	 
    <bean id="accountprofiledao"
          class="test.AccountProfileDaoImp" >
          <property name="dataSource" ref="datasource" />
    </bean>

<p class="indent">


事務管理器配置:

    <bean id="dbTransactionManager"
    	  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	  <property name="dataSource" ref="datasource" />
    </bean>
<p class="indent">


業務門面:

    <bean id="accountservice_target"
    	  class="test.AccountService" >
    	  <property name="accountDao" ref="accountdao" />
    	  <property name="accountProfileDao" ref="accountprofiledao" />    	  
    </bean>

<p class="indent">


最後配置Spring的事務代理(其實就是利用了aop):

    <bean id="accountservice" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
    	<property name="transactionManager" ref="dbTransactionManager" />
    	<property name="target" ref="accountservice_target" />
    	<property name="transactionAttributes" >
    		<props>
    			<prop key="register*">PROPAGATION_REQUIRED</prop>
    		</props>
    	</property>
    </bean>

<p class="indent">


我的業務門面實現有個方法:

	public void registerAccount(Account a, AccountProfile ap){
		accountDao.insert(a);
		accountProfileDao.insert(ap);		
	}
<p class="indent">


分別呼叫2個dao的insert()方法,Account, AccountProfile是值物件。

測試程式碼:

	public static void main(String[] args) {
		FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");
		
		AccountService service = (AccountService) context.getBean("accountservice");
		
		Account a = new Account();
		a.setId("U001");
		a.setName("zc");
		a.setPhone("123");
		
		AccountProfile ap = new AccountProfile();
		ap.setName(a.getName()); // "zc"
		ap.setPassword("abcdef");
		
		service.registerAccount(a,ap);

		a = new Account();
		a.setId("U002");
		a.setName("zc");
		a.setPhone("123");
		
		ap = new AccountProfile();
		ap.setName(a.getName()); // "zc"
		ap.setPassword("12345");
		
		service.registerAccount(a,ap);
		
		context.close();

	}

<p class="indent">


由於表accountprofile 的name 欄位是唯一的,所以第2次registerAccount()要出現異常。

也就是在第2次執行registerAccount()時

{
		accountDao.insert(a);
		accountProfileDao.insert(ap);  // 這要丟擲異常		
}

<p class="indent">


但前面的 accountDao.insert(a) 無法回滾呢?

資料庫結果:account有2條記錄,id不同,但name相同, accountprofile有1條記錄.

資料庫不一致, 事務沒起到作用。




相關文章