spring学习笔记(7)——spring事务管理方式

来源:互联网 发布:德卡斯特里奥算法 编辑:程序博客网 时间:2024/06/05 05:19

spring事务管理有两种方式:一种是传统的编程式事务管理,即通过编写代码实现事务的管理,包括定义事务的开始、程序正常执行后事务提交、异常时进行事务回滚。
另一种是基于AOP技术实现的声明式事务,其主要思想是将事务管理作为一个“方面”代码单独编写,程序员只关心核心业务逻辑代码,然后通过AOP技术将事务管理的“方面”代码织入到业务类中。

下面通过一个银行转账的例子说明事务:
首先先配置好ssh框架见spring笔记(6)。

  1. 数据库实体类和映射文件
    这里写图片描述
    实体类:
package com.test.bean;public class Account {    private int id;    private String accountNo;    private double balance;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getAccountNo() {        return accountNo;    }    public void setAccountNo(String accountNo) {        this.accountNo = accountNo;    }    public double getBalance() {        return balance;    }    public void setBalance(double balance) {        this.balance = balance;    }}

2、DAO层

package com.test.dao;import java.util.List;import com.test.bean.Account;public interface AccountDAO {    // 根据账号获取账户对象    public List getAccountByAccountNo(String accountNo);    // 转账    public void transfer(Account a1, Account a2);}
package com.test.dao.impl;import java.util.List;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import com.test.bean.Account;import com.test.dao.AccountDAO;public class AccountDAOImpl extends HibernateDaoSupport implements AccountDAO {    //转账    public void transfer(Account a1, Account a2) {        this.getHibernateTemplate().update(a1);        this.getHibernateTemplate().update(a2);    }    //根据账号获取账户对象    public List getAccountByAccountNo(final String accountNo) {        // TODO Auto-generated method stub        String hql ="from Account account where account.accountNo=?";           return this.getHibernateTemplate().find(hql,accountNo);    }}

3、service层

package com.test.service;import java.util.List;import com.test.bean.Account;public interface AccountService {    // 根据账号获取账户对象    public List getAccountByAccountNo(String accountNo);    // 转账    public void transfer(Account a1, Account a2);}
package com.test.service.impl;import java.util.List;import com.test.bean.Account;import com.test.dao.AccountDAO;import com.test.service.AccountService;public class AccountServiceImpl implements AccountService{    //用AccountDAO接口声明对象,并添加set方法用于依赖注入    AccountDAO accountDAO;    public void setAccountDAO(AccountDAO accountDAO) {        this.accountDAO = accountDAO;    }    //转账    //使用@Transactional注解实现transfer方法的事务管理    public void transfer(Account a1, Account a2) {        accountDAO.transfer(a1, a2);    }    //根据账号获取账户对象    public List getAccountByAccountNo(String accountNo) {        // TODO Auto-generated method stub        return accountDAO.getAccountByAccountNo(accountNo);    }}

4、action层

package com.test.action.account;import java.util.List;import com.opensymphony.xwork2.ActionSupport;import com.test.bean.Account;import com.test.service.AccountService;public class AccountManagerAction extends ActionSupport {    // 定义属性,用于封装表单数据    private String ac1;    private String ac2;    private String amount;    public String getAc1() {        return ac1;    }    public void setAc1(String ac1) {        this.ac1 = ac1;    }    public String getAc2() {        return ac2;    }    public void setAc2(String ac2) {        this.ac2 = ac2;    }    public String getAmount() {        return amount;    }    public void setAmount(String amount) {        this.amount = amount;    }    // 使用AccountBiz接口声明对象,并添加set方法用于依赖注入    private AccountService service;    public void setAccountService(AccountService service) {        this.service = service;    }    @Override    // 执行请求    public String execute() throws Exception {        System.out.println(ac1);        System.out.println(ac2);        Account a1 = null;        Account a2 = null;        // 获取账号ac1的账户对象,并更新对象中的账户余额属性        List list1 = service.getAccountByAccountNo(ac1);        if (list1.size() > 0) {            a1 = (Account) list1.get(0);            System.out.println("ac1");            a1.setBalance((a1.getBalance() - Double.parseDouble(amount)));        }        // 获取账号ac2的账户对象,并更新对象中的账户余额属性        List list2 = service.getAccountByAccountNo(ac2);        if (list2.size() > 0) {            a2 = (Account) list2.get(0);            System.out.println("ac2");            a2.setBalance((a2.getBalance() + Double.parseDouble(amount)));        }        try {            // 执行转账操作            service.transfer(a1, a2);            System.out.println("transfer");        } catch (Exception e) {            // 转账失败            System.out.println(e);            return "error1";        }        // 转账成功        return "success1";    }}

5、spring配置文件applicationContext.xml中配置相关类

<!--        定义AccountDAOImpl类实例,并将已经创建LocalSessionFactoryBean的实例        sessionFactory依赖注入到UserDAOImpl类所继承的 HibernateDaoSupport        的sessionFactory属性    -->    <bean id="accountDAO" class="com.test.dao.impl.AccountDAOImpl">        <property name="sessionFactory" ref="sessionFactory" />    </bean>    <bean id="accountService" class="com.test.service.impl.AccountServiceImpl">        <property name="accountDAO" ref="accountDAO" />    </bean>    <!--        部署Struts 2的负责账户管理的控制器AccountManager    -->    <bean id="amAction" class="com.test.action.account.AccountManagerAction">        <property name="accountService" ref="accountService" />    </bean>

6、struts.xml配置

<action name="doTransfer" class="amAction">            <!-- 定义处理结果和资源之间的映射关系 -->            <result name="error1">error1.jsp</result>            <result name="success1">success1.jsp</result></action>

7、配置声明事务
(1)、在spring配置文件中增加事务管理所需的常用命名空间声明

<beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    http://www.springframework.org/schema/tx     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd     http://www.springframework.org/schema/aop     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

(2)、声明事务管理器,在声明事务管理器时需要注入sessionFactory属性。定义事务通知,定义事务通知时需要指定一个事务管理器,然后在其属性中声明事务规则。

    <!-- 声明事务管理器 -->    <bean id="transactionManager"        class="org.springframework.orm.hibernate3.HibernateTransactionManager">        <property name="sessionFactory">            <ref bean="sessionFactory" />        </property>    </bean>    <!-- 定义事务通知 -->    <tx:advice id="txAdvice" transaction-manager="transactionManager">        <!-- 指定事务传播规则 -->        <tx:attributes>            <!-- 对get打头的方法应用SUPPORTS事务规则 -->            <tx:method name="get*" propagation="SUPPORTS" />            <!-- 对其他方法应用REQUIRED事务规则 -->            <tx:method name="*" propagation="REQUIRED"></tx:method>        </tx:attributes>    </tx:advice>    <!-- 定义切面,并将事务通知和切面组合(定义哪些方法应用事务规则) -->    <aop:config>        <aop:pointcut id="serviceMethods" expression="execution(* com.test.service.*.*(..))" />        <!-- 将事务通知和切面组合 -->        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />    </aop:config>

8、编写测试页面

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags"%> <html>     <head>        <title>转账页面</title>    </head>    <body>       <s:form action="doTransfer.action">            <s:textfield name="ac1" label="账户1"  />              <s:textfield name="ac2" label="账户2"  />              <s:textfield name="amount" label="转账金额"  />              <s:submit value="转账"  />        </s:form>    </body></html>

第一次测试:
这里写图片描述
数据库:
这里写图片描述
第二次测试:
这里写图片描述
数据库:
这里写图片描述
账户输入错误,两个账户余额均不变化。
第三次测试:
将spring配置文件中一下代码删去,及删除声明式事务。重启工程后。
在执行第二次的操作:
这里写图片描述

0 0
原创粉丝点击