Spring allows us to add transactions into our code without having to deal directly with the JDBC classes. For that purpose, Spring provides a transaction management package that not only replaces JDBC transaction management, but also enables declarative transaction management (configuration instead of code).
Spring允许我们在代码中添加事务,而不必直接处理JDBC类.为此,Spring提供了一个事务管理包,它不仅取代了JDBC事务管理,同时也支持声明式事务管理(配置而不是代码)
To use transactional database access, we will need to change the storage engine of the tables in the world database. The downloaded script explicitly creates MyISAM tables, which do not support transactional semantics. The InnoDB storage engine does support transactions and this is what we will be using. We can change the storage engine with the following statements.
为了使用事务访问数据库,我们需要更改world数据库中表的存储引擎。下载的脚本显式创建不支持事务语义的MyISAM表。InnoDB存储引擎却支持事务,这就是我们将要使用的。我们可以使用以下语句更改存储引擎。
ALTER TABLE City ENGINE=InnoDB;
ALTER TABLE Country ENGINE=InnoDB;
ALTER TABLE CountryLanguage ENGINE=InnoDB;
A good programming practice emphasized by Spring is separating interfaces and implementations. What this means is that we can create a Java interface and only use the operations on this interface without any internal knowledge of what the actual implementation is. We will let Spring manage the implementation and with this it will manage the transactions for our implementation.
Spring强调的一个好的编程实践是分离接口和实现。这意味着我们可以创建一个Java接口,并且尽管使用该接口上的操作,而不需要了解实际实现是什么。我们将让Spring管理实现,并以此管理实现的事务。
First you create a simple interface:
public interface Ex3Dao {
Integer createCity(String name, String countryCode,
String district, Integer population);
}
This interface contains one method that will create a new city record in the database and return the id of the new record. Next you need to create an implementation of this interface.
此接口包含一个方法,该方法将在数据库中创建新的城市记录并返回新记录的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();
}
}
You can see that we only operate on abstract query objects here and do not deal directly with the JDBC API. Also, this is the complete implementation. All of our transaction management will be dealt with in the configuration. To get the configuration started, we need to create the DAO.
可以看到,这里我们只对抽象查询对象进行操作,而不直接处理JDBCAPI。而且,这是完整的实现。我们的所有事务管理都将在配置中处理。要开始配置,我们需要创建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>
The preceding code creates a transaction manager that handles transactions for the data source provided to it. The txAdvice
uses this transaction manager and the attributes specify to create a transaction for all methods. Finally we need to apply this advice with an AOP pointcut.
前面的代码创建了一个事务管理器,用于处理提供给它的数据源的事务。txAdvice使用此事务管理器和指定的属性为所有方法创建事务。最后,我们需要用AOP切入点应用这个advice。
<aop:config>
<aop:pointcut id="daoMethods"
expression="execution(* code.Ex3Dao.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods"/>
</aop:config>
This basically says that all methods called on the Ex3Dao
interface will be wrapped in a transaction. To make use of this, we only have to retrieve the dao
from the application context and call a method on the dao
instance.
这基本上意味着在Ex3Dao接口上调用的所有方法都将包装在一个事务中。为了利用这一点,我们只需要从应用程序上下文中检索dao并在dao实例上调用一个方法。
Ex3Dao dao = (Ex3Dao) ctx.getBean("dao");
Integer id = dao.createCity(name, countryCode, district, pop);
We can verify from this that there is no transaction management happening in our Java code and it is all configured with Spring. This is a very powerful notion and regarded as one of the most beneficial features of Spring.
由此我们可以看出,在我们的Java代码中没有事务管理,都是用Spring配置的。这是一个非常强大的概念,被认为是Spring最有益的特性之一。