编程式的事务管理

编程式事务提供了 TransactionTemplate 模板类,该类可以大大减少事务操作的代码。因此 TransactionTemplate 采用 Callback 避免让开发者重复书写其打开事务、提交事务及回滚事务等代码,同时 TransactionTemplate 无须书写大量的 t可...catch 块。HibernateTemplate 必须提供 PlatformTransactionManager 实例。该实例既可以在代码中手动设置,也可以使用 Spring 的依赖注入。总之,只要获取了PlatformTransactionManager 引用, TransactionTemplate 就可以完成事务操作。

使用 TransactionTemplate 不需要显式地开始事务,甚至不需要显式地提交事务。这些步骤都由模板完成。但出现异常时,应通过 TransactionStatus 的 setRollbackOnly 显式回攘事务。

TransactionTemplate 的 execute 方法接收一个 TransactionCallback 实例。 Callback 也是 Spring 的经典设计,用于简化用户操作,TransactionCallback 包含如下方法。

ObjectdolnTransaction(TransactionStatusstatus)。

该方法的方法体就是事务的执行体。

如果事务的执行体没有返回值,则可以使用TransactionCallbackWithoutResult1类的实例。这是个抽象类,不能直接实例化,只能用于创建匿名内部类。它也是TransactionCallback接口的子接口,该抽象类包含一个抽象方法:


voiddolnTransactionWithoutResult(TransactionStatusstatus)


该方法与 dolnTransaction 的效果非常相似,区别在于该方法没有返回值,即事务执行体无须返回值。

在下面的示例中,PlatformTransactionManager实例采用适用于 Hibernate 的事务管理器来实现类 HibernateTransactionManager,该实现类是个局部事务管理器,容器中仅仅部署了该事务管理器 bean,因此应在代码中于动为 TransactionTemplate 注入事务管理器bean。下面是 Hibernate 局部事务管理的配置文件的源代码:

<?xml version="1.0" encoding="gb2312"?>
<!--Spring配置文件的DTD定义-->
<!DOCTYPE beansPUBLiC"-//SPRING//DTD BEAN//EN"''http://www.springfrarnework.org/dtd/spring-beans.dtd">
<!--Spring配置文件的根元素是beans-->
<beans>
<!--定义数据源,该bean的 ID 为 dataSource-->
<bean id="dataSource" class="org.springfrarnework.jdbc.datasource.DriverManagerDataSource">
<!--指定数据库驱动-->
<property name="driverClassNarne"><value>corn.rnysql.jdbc.Driver</value>
</property>
<!--指定连接数据库的URL-->
<property name="url"><vaiue>jdbc:rnysql://wonder:3306/j2ee</value>
</property>
<!--root 为数据库的用户名-->
<property name="username"><value>root</value></property>
<!--pass 为数据库密码-->
<property name="password"><value>pass</value></property></bean>
<!--定义Hibernate的 SessionFactory-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!--依赖注入数据源,注入上文定义的dataSource-->
<property name="dataSource"><ref local="dataSource"></property>
<!-- mappingResouces属性用来列出全部映射文件>
<property name="mappingResources"><list>
<!以下用来列出所有的PO 映射文件-->
<value>lee/MyTest.hbm.xml</value></list></property>
<!--定义Hibernate的 SessionFactory的属性-->
<property name="hibernateProperties"><props>
<!--指定 Hibernate的连接方法-->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!不同数据库连接,启动时选择create,update, create-drop-->
<prop key="hibernate.hbm2ddl.auto">update</prop></props></property></bean>
<!--配置Hibernate的事务管理器-->
<!--使用HibernateTransactionManager类,该类是PlatformTransactionManager接口针对采用Hibernate持久化连接的特定实现。-->
<bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- HibernateTransactionManager bean需要依赖注入一个SessionFactory bean的引用-->
<property name="sessionFactory">
<ref local="sessionFactory"></property></bean></beans>

下面是采用TransactionTemplate和 HibemateTemplate的事务操作代码:

public class TransactionTest{
public static void main(String[] args){
//因为并未在 web 应用中测试,故需要手动创建 Spring 的上下文
final ApplicationContext ctx =new FileSystemXrnlApplicationContext("bean.xml");
//获得 Spring上下文的事务管理器
PlatformTransactionManager transactionManager=(PlatformTransactionManager)ctx.getBean("transactionManager");final SessionFactory sessionFactory =(SessionFactory)ctx.getBean("sessionFactory");
//以事务管理器实例为参数,创建TransactionTemplate对象
TransactionTemplate tt = new TransactionTemplate(transactionManager);
//设置TransactionTemplate的事务传播属性
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUlRED);
//执行TransactionTemplate的 execute方法,该方法需要TransactionCallback实例tt.execute(newTransactionCallbackWithoutResult()
//采用 TransactionCallbackWithoutResult匿名内部类的形式执行
protectedvoid dolnTransactionWithoutResult(TransactionStatus ts)try{
//以 SessionFactory 实例为参数创建 HibernateTemplateHibernateTemplate hibernateTemplate=new HibernateTemplate(sessionFactory);
MyTestpl=newMyTest ("Jack");
//保存第一个实例
hibernateTemplate.save(pl);
//让下面的数据库操作抛出异常即可看出事务效果。前面的操作也不会生效
MyTestp2=new MyTest ("Jack");
//保存第二个实例,可将Person的 name属性设为标识属性,并引起主键重复的异常,可看出前一条记录也不会加入数据库中
hibernateTemplate.save(p2);
}catch (Exception e){
ts.setRollbackOnly();.,)} 

查看数据库的 mytable 表,该表中没有任何记录(如果没有采用事务,第一条记录应该可以进去。而两次保存记录放在 doInTransactionWithoutResult 方法中执行),因为该方法的方法体具有事务性,该方法的数据库操作要么全部生效,要么全部失效。由于第二条记录违反了数据库的主键约束,因此,记录全部失效。

你可能感兴趣的:(spring,编程,Hibernate,bean,配置管理)