3.13.2 事务性 JDBC 访问

Spring 允许我们将事务添加到我们的代码中,而不必直接处理 JDBC 类。为此,Spring 提供了一个事务管理包,它不仅可以替代 JDBC 事务管理,还可以启用声明式事务管理(配置而不是代码)。

要使用事务数据库访问,我们需要更改世界数据库中表的存储引擎。下载的脚本显式创建不支持事务语义的 MyISAM 表。InnoDB 存储引擎确实支持事务,这就是我们将要使用的。我们可以使用以下语句更改存储引擎。

ALTER TABLE City ENGINE=InnoDB;
ALTER TABLE Country ENGINE=InnoDB;
ALTER TABLE CountryLanguage ENGINE=InnoDB;

Spring 强调的一个良好的编程习惯是分离接口和实现。这意味着我们可以创建一个 Java 接口,并且只使用这个接口上的操作,而无需了解实际实现是什么。我们将让 Spring 管理实现,并以此管理我们实现的事务。

首先创建一个简单的界面:

public interface Ex3Dao {
    Integer createCity(String name, String countryCode,
    String district, Integer population);
}

此接口包含一个方法,该方法将在数据库中创建新的城市记录并返回新记录的 ID。接下来您需要创建此接口的实现。

public class Ex3DaoImpl implements Ex3Dao {
    protected DataSource dataSource;
    protected SqlUpdate updateQuery;
    protected SqlFunction idQuery;
    public Integer createCity(String name, String countryCode,
        String district, Integer population) {
            updateQuery.update(new Object[] { name, countryCode,
                   district, population });
            return getLastId();
        }
    protected Integer getLastId() {
        return idQuery.run();
    }
}

可以看到我们这里只对抽象的查询对象进行操作,并没有直接和JDBC API打交道。另外,这是完整的实现。我们所有的事务管理都会在配置中处理。要开始配置,我们需要创建 DAO。

<bean id="dao" class="code.Ex3DaoImpl">
    <property name="dataSource" ref="dataSource"/>
    <property name="updateQuery">...</property>
    <property name="idQuery">...</property>
</bean>

现在我们需要设置事务配置。我们必须做的第一件事是创建事务管理器来管理数据源和方法所需事务属性的规范dao

<bean id="transactionManager"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

前面的代码创建了一个事务管理器,用于处理提供给它的数据源的事务。使用 txAdvice此事务管理器和属性指定为所有方法创建事务。最后,我们需要通过 AOP 切入点来应用此建议。

<aop:config>
    <aop:pointcut id="daoMethods"
        expression="execution(* code.Ex3Dao.*(..))"/>
     <aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods"/>
</aop:config>

这基本上表示在 Ex3Dao接口上调用的所有方法都将包装在一个事务中。要使用它,我们只需 dao从应用程序上下文中检索并调用dao实例上的方法。

Ex3Dao dao = (Ex3Dao) ctx.getBean("dao");
Integer id = dao.createCity(name,  countryCode, district, pop);

由此可以验证,我们的Java代码中并没有发生事务管理,都是用Spring配置的。这是一个非常强大的概念,被认为是 Spring 最有益的特性之一。