2

我正在使用 Spring(3.0 版)'@Transactional' 注释来演示 Spring 中的事务支持,但无法使其正常工作(尽管在本论坛和其他技术论坛中看到了人们遇到的类似问题)。

这是我的 Spring 配置条目spring-application-context.xml

<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

在此异常之后,我本来希望看到没有任何东西提交给数据库。

有谁知道我哪里出错了,我在这里错过了一些关键概念吗?

任何帮助将不胜感激!

4

1 回答 1

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 事务管理

于 2011-03-18T11:42:34.023 回答