2011-03-18 140 views
2

爲了演示Spring中的事務支持 ,我使用了Spring(3.0版)'@Transactional'註釋,但無法正常工作(儘管看到過類似人們在此遇到的問題以及其他技術論壇)。在使用Spring 3時,事務不會回滾@Transactional註釋

這裏是spring-application-context.xml我的Spring配置項:

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

    <tx:annotation-driven /> 

    <bean id="formatDao" class="com.gj.dao.FormatDao"> 
    <property name="dataSource" ref="dataSource"/> 
    </bean> 

這是我在我的測試類交易方法:

@Transactional(readOnly = true) 
    public class FormatDaoTest 
    { 

     private static ApplicationContext context = new FileSystemXmlApplicationContext(
     "c:\\catalogue\\src\\com\\gj\\conf\\spring-application-context.xml"); 

     public static void main(String[] args) 
     { 
    FormatDaoTest test = new FormatDaoTest(); 
    test.doTransaction(); 
     } 


     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false) 
     public void doTransaction() 
     { 

    IDao dao = (IDao) context.getBean("formatDao"); 

    Format newFormat = new Format(1, "Test Format 1"); 

    // Creating a single format 
    dao.create(newFormat); 

    List newFormatList = new ArrayList(); 
    newFormatList.add(new Format(2, "Test Format 2")); 
    newFormatList.add(new Format(3, "Test Format 3")); 
    newFormatList.add(new Format(4, "Test Format 4")); 
    newFormatList.add(new Format(5, "Test Format 5")); 

    // Creating a list of formats 
    dao.create(newFormatList); 

    List updatedFormatList = new ArrayList(); 
    updatedFormatList.add(new Format(1, "My Test Format 1")); 
    updatedFormatList.add(new Format(2, "My Test Format 2")); 
    updatedFormatList.add(new Format(3, "My Test Format 3")); 

    // Update a list of formats 
    dao.update(updatedFormatList); 

    Format updatedFormat = new Format(4, "My Test Format 4 with a long format description so allowed table column size is exceeded"); 

    // Update a single format resulting in a java.sql.SQLException: ORA-12899: value too large for column 
    // "RSSPPF1_OWNER"."FORMAT"."FORMAT_DESC" (actual: 88, maximum: 30) 
    dao.update(updatedFormat); 


     } 

    } 

以下SQL異常被拋出(因爲我所期望的):

Exception in thread "main" org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [UPDATE FORMAT SET format_desc = ? WHERE format_id = ?]; SQL state [72000]; error code [12899]; ORA-12899: value too large for column "RSSPPF1_OWNER"."FORMAT"."FORMAT_DESC" (actual: 88, maximum: 30) 
    ; nested exception is java.sql.SQLException: ORA-12899: value too large for column "RSSPPF1_OWNER"."FORMAT"."FORMAT_DESC" (actual: 88, maximum: 30) 

    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:602) 
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:811) 
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:833) 
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:260) 
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:264) 
    at com.gj.dao.FormatDao.update(FormatDao.java:68) 
    at com.gj.test.FormatDaoTest.doTransaction(FormatDaoTest.java:62) 
    at com.gj.test.FormatDaoTest.main(FormatDaoTest.java:26) 
    Caused by: java.sql.SQLException: ORA-12899: value too large for column "RSSPPF1_OWNER"."FORMAT"."FORMAT_DESC" (actual: 88, maximum: 30) 

    at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70) 
    at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:131) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:204) 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:455) 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:413) 
    at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:1034) 
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:194) 
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:953) 
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1222) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3387) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3468) 
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1062) 
    at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:817) 
    at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:1) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586) 
    ... 7 more 

但是,在異常被拋出後,交易會上不會回退,我可以看到以前的數據庫被拋出一直致力於FORMAT表外插 和更新之前:

FORMAT_ID FORMAT_DESC 
    1  My Test Format 1 
    2  My Test Format 2 
    3  My Test Format 3 
    4  Test Format 4 
    5  Test Format 5 

我本來期望看到沒有提交到數據庫這個異常以下。

有沒有人知道我要去哪裏錯了,我在這裏錯過了一些關鍵概念?

任何幫助將不勝感激!

回答

6

@Transactional僅適用於Spring管理的bean(除非您配置了高級功能),而在您的情況下,FormatDaoTest不受Spring管理。

我想你可以做以下的快速修復:

public static void main(String[] args) { 
    FormatDaoTest test = context.getAutowireCapableBeanFactory() 
     .createBean(FormatDaoTest.class); 
    test.doTransaction(); 
} 

作爲一個更優雅的解決方案,你可以使用Spring TestContext框架,它支持事務感知測試開箱,見9.3.5.4 Transaction management

+0

Grr,正是我會寫的:-)(+1) – 2011-03-18 12:05:42

+0

非常感謝!必須是真正明顯的東西。 – user665909 2011-03-18 12:07:33

+0

不得不下載'cglib_2.2.jar'並添加到我的類路徑中以使其工作。我會認爲SPRING FRAMEWORK 3.1 M1會包含所有的依賴類嗎?似乎有一個主題,我需要下載其他依賴瓶來克服我打的錯誤! – user665909 2011-03-18 12:56:19

相關問題