`
liu0107613
  • 浏览: 71691 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Spring的事务管理例子代码

    博客分类:
  • java
阅读更多

事务管理:

  分global事务管理和local事务管理,global要跨越多个事务资源,而local一般是本地资源,如JDBC,比较好控制。

 

下面的例子展示怎么Spring的事务管理。声明式事务管理

 

 

其实个人感觉还是手工控制事务舒服一些,因为被Spring管理后,觉得真的很简单了,特感觉没有深度东西可以做了。。。个人感受。

此代码是ProSpring书上面,经过简单改造,用Mysql数据库,把不完整的代码补充完整。

 

数据库:


DROP TABLE IF EXISTS `accounts`;
CREATE TABLE `accounts` (
  `AccountId` int(10) unsigned NOT NULL auto_increment,
  `AccountNumber` varchar(20) NOT NULL,
  `Balance` decimal(10,2) NOT NULL,
  PRIMARY KEY  (`AccountId`),
  UNIQUE KEY `AccountId` (`AccountNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

 

DROP TABLE IF EXISTS `history`;
CREATE TABLE `history` (
  `HistoryId` bigint(20) unsigned NOT NULL auto_increment,
  `Account` varchar(20) NOT NULL,
  `Operation` varchar(50) NOT NULL,
  `Amount` decimal(10,2) NOT NULL,
  `TransactionDate` timestamp NOT NULL,
  `TargetAccount` varchar(20) default NULL,
  UNIQUE KEY `HistoryId` (`HistoryId`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

--
-- Dumping data for table `history`
--

 

接口操作方法:

  package com.apress.prospring.ch12.business;

import java.math.BigDecimal;

import com.apress.prospring.ch12.domain.Account;
   
public interface AccountManager {
 
    /**
     * 插入账户
     * @param account
     */
    public void insert(Account account);
   
    /**
     * 往账户里面存钱
     * @param accountId
     * @param amount
     */
    public void deposit(String accountId, BigDecimal amount);
   
    /**
     * 从sourceAccount往targetAccount转账
     * @param sourceAccount
     * @param targetAccount
     * @param amount
     */
    public void transfer(String sourceAccount, String targetAccount, BigDecimal amount);
   
    /**
     * 数据库中账户的数量
     * @return
     */
    public int count();
}

 

抽象类实现:

 

package com.apress.prospring.ch12.business;

import java.math.BigDecimal;
import java.util.Date;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.InitializingBean;

import com.apress.prospring.ch12.domain.Account;
import com.apress.prospring.ch12.domain.AccountDao;
import com.apress.prospring.ch12.domain.History;
import com.apress.prospring.ch12.domain.HistoryDao;

public abstract class AbstractAccountManager
implements InitializingBean, AccountManager {
private AccountDao accountDao;
private HistoryDao historyDao;

protected void doInsert(Account account) {
    getAccountDao().insert(account);
    History history = new History();
    history.setAccount(account.getAccountNumber());
    history.setAmount(account.getBalance());
    history.setOperation("Initial deposit");
    history.setTargetAccount(null);
    history.setTransactionDate(new Date());
    getHistoryDao().insert(history);
}

protected void doDeposit(String accountId, BigDecimal amount) {
    History history = new History();
    history.setAccount(accountId);
    history.setAmount(amount);
    history.setOperation("Deposit");
    history.setTargetAccount(null);
    history.setTransactionDate(new Date());

    getAccountDao().updateBalance(accountId, amount);
    getHistoryDao().insert(history);
}

protected void doTransfer(String sourceAccount,
  String targetAccount, BigDecimal amount) {
    Account source = getAccountDao().getAccountById(sourceAccount);

    if (source.getBalance().compareTo(amount) > 0) {
        // transfer allowed
        getAccountDao().updateBalance(sourceAccount, amount.negate());
        getAccountDao().updateBalance(targetAccount, amount);

        History history = new History();
        history.setAccount(sourceAccount);
        history.setAmount(amount);
        history.setOperation("Paid out");
        history.setTargetAccount(targetAccount);
        history.setTransactionDate(new Date());
        getHistoryDao().insert(history);

        history = new History();
        history.setAccount(targetAccount);
        history.setAmount(amount);
        history.setOperation("Paid in");
        history.setTargetAccount(sourceAccount);
        history.setTransactionDate(new Date());
        getHistoryDao().insert(history);
    } else {
        throw new RuntimeException("Not enough money");
    }
}

protected int doCount() {
    return getAccountDao().getCount();
}   


public final void afterPropertiesSet() throws Exception {
    if (accountDao == null) throw new
        BeanCreationException("Must set accountDao");
    if (historyDao == null) throw new
        BeanCreationException("Must set historyDao");
    initManager();
}

protected void initManager() {
   
}

protected AccountDao getAccountDao() {
    return accountDao;
}

public void setAccountDao(AccountDao accountDao) {
    this.accountDao = accountDao;
}

protected HistoryDao getHistoryDao() {
    return historyDao;
}

public void setHistoryDao(HistoryDao historyDao) {
    this.historyDao = historyDao;
}
}

默认实现:

package com.apress.prospring.ch12.business;

import java.math.BigDecimal;

import com.apress.prospring.ch12.domain.Account;

public class DefaultAccountManager extends AbstractAccountManager {
   
    public void insert(Account account) {
        doInsert(account);
    }
   
    public void deposit(String accountId, BigDecimal amount) {
        doDeposit(accountId, amount);
    }
   
    public void transfer(String sourceAccount, String targetAccount, BigDecimal amount) {
        doTransfer(sourceAccount, targetAccount, amount);
    }

 public int count() {
  return 0;
 }
   
}

 

数据库操作的两个接口类dao

 

 

 

package com.apress.prospring.ch12.domain;

import java.math.BigDecimal;

public interface AccountDao {
   
 
 /**
  * get account by account number
  * @param accountId
  * @return
  */
 public Account getAccountById(String accountId);

 /**
  * @param sourceAccount
  * @param amount
  */
 public void updateBalance(String sourceAccount, BigDecimal amount);

 /**
  * @param account
  */
 public void insert(Account account);

 /**
  * @return
  */
 public int getCount();

}

package com.apress.prospring.ch12.domain;
   
// in HistoryDao.java:
import java.util.List;
   
public interface HistoryDao {
    public List getByAccount(int account);
    public History getById(int historyId);
    public void insert(History history);
}

AccountDao.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>

    <typeAlias type="com.apress.prospring.ch12.domain.Account" alias="account"/>
    <resultMap class="account" id="result">
        <result property="accountNumber" column="AccountNumber"/>
        <result property="balance" column="Balance"/>
    </resultMap>   
     <insert id="insertAccout" parameterClass="account">
        insert into accounts (AccountNumber, Balance) values (#accountNumber#,#balance#)
    </insert>
   
   
    <select id="getAccountById" resultMap="result" parameterClass="int" >
        select * from accounts where AccountNumber=#value#
    </select>
   
   
   
    <update id="update" parameterClass="map">
        update accounts set  Balance=#balance# where AccountNumber=#accountNumber#
    </update>
   
   
</sqlMap>

 

HistoryDao.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>

    <typeAlias type="com.apress.prospring.ch12.domain.History" alias="history"/>
    <resultMap class="history" id="result">
        <result property="account" column="Account"/>
        <result property="operation" column="Operation"/>
        <result property="amount" column="Amount"/>
        <result property="transactionDate" column="TransactionDate"/>
        <result property="targetAccount" column="TargetAccount"/>
    </resultMap>   
     <insert id="insertHistory" parameterClass="history">
        insert into history (Account,Operation,Amount,TransactionDate, TargetAccount)
        values (#account#,#operation#,#amount#,#transactionDate#,#targetAccount#)
    </insert>
   

   
</sqlMap>

 

applicationContext.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
   
<beans>
   
    <!-- Data source bean -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"    destroy-method="close" >
        <property name="driverClassName">
            <value>com.mysql.jdbc.Driver</value>
        </property>
        <property name="url">
            <value>jdbc:mysql://localhost/test</value></property>
        <property name="username"><value>root</value></property>
        <property name="password"><value>G@111111</value></property>
    </bean>
   
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource"><ref local="dataSource"/></property>
    </bean>
   
    <bean id="sqlMapClient"
        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation"><value>sqlMapConfig.xml</value></property>
    </bean>
   
    <bean id="accountDao"
        class="com.apress.prospring.ch12.data.SqlMapClientAccountDao">
        <property name="dataSource"><ref local="dataSource"/></property>
        <property name="sqlMapClient"><ref local="sqlMapClient"/></property>
    </bean>
   
    <bean id="historyDao"
        class="com.apress.prospring.ch12.data.UnreliableSqlMapClientHistoryDao">
        <property name="dataSource"><ref local="dataSource"/></property>
        <property name="sqlMapClient"><ref local="sqlMapClient"/></property>
    </bean>
   
    <bean id="accountManagerTarget"
        class="com.apress.prospring.ch12.business.DefaultAccountManager">
        <property name="accountDao"><ref local="accountDao"/></property>
        <property name="historyDao"><ref local="historyDao"/></property>
    </bean>
   
    <bean id="accountManager"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager">
            <ref bean="transactionManager"/></property>
        <property name="target"><ref local="accountManagerTarget"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="insert*">
                    PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                <prop key="transfer*">
                    PROPAGATION_REQUIRED, ISOLATION_SERIALIZABLE</prop>
                <prop key="deposit*">
                    PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
            </props>
        </property>
    </bean>
</beans>

 

 

package com.apress.prospring.ch12.business;

import java.math.BigDecimal;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.apress.prospring.ch12.domain.Account;

public class AccountManagerTest {
   
    private ApplicationContext context;
   
    private void run() {
        System.out.println("Initializing application");
        context = new ClassPathXmlApplicationContext(new String[] {
            "applicationContext.xml" });
        AccountManager manager = (AccountManager)context.getBean(
            "accountManager");
       
        int count = manager.count();
        int failures = 0;
        int attempts = 100;
       
        for (int i = 0; i < attempts; i++) {
            Account a = new Account();
            a.setBalance(new BigDecimal(10));
            a.setAccountNumber("123 " + i);

            try {
                manager.insert(a);
            } catch (RuntimeException ex) {
                System.out.println("Failed to insert account " + ex.getMessage());
                failures++;
            }
        }
       
        System.out.println("Attempts  : " + attempts);
        System.out.println("Failures  : " + failures);
        System.out.println("Prev count: " + count);
        System.out.println("New count : " + manager.count());
       
        System.out.println("Done");
    }
   
    public static void main(String[] args) {
        new AccountManagerTest().run();
    }
   
}

 

 

 

分享到:
评论

相关推荐

    Spring 事务 代码

    spring 的声明式事务处理的简单例子。我已经测试过能用,能回滚。但例子是入门级别的,如果需要学更高深的请绕道。

    spring事务-项目案例-PPT解读.zip

    spring事务_案例_PPT 一、事务传播机制的demo案例,内容包括: 1.业务代码列举7种事务传播机制的情况,每个测试方法都附带日志分析记录、使用场景和实际场景,小白也能看得懂!!! 2.在测试类Test包下,使用juniter...

    Spring 3.0就这么简单源代码

    本书主要介绍了Spring 3.0的核心内容,不仅讲解了Spring 3.0的基础知识,还深入讨论了Spring IoC容器、Spring AOP、使用Spring JDBC访问数据库、集成Hibernate、Spring的事务管理、Spring MVC、单元测试、敏捷开发...

    Spring Nested事务简单案例

    这里是Spring的一个Nested事务的代码及数据库文件,因为NESTED资源很少,这里作出了一个通俗易懂的 让需要者下载。

    spring boot 全面的样例代码

    - chapter1:[基本项目构建(可作为工程脚手架),引入web模块,完成一个简单的RESTful API]...- 不错的spring boot实践学习案例:https://git.oschina.net/jeff1993/springboot-learning-example

    Spring3.0配置多个事务管理器的方法

    Spring3.0配置多个事务管理器(即操作多个数据源)的方法 大多数项目只需要一个事务管理器。然而,有些项目为了提高效率、或者有多个完全不同又不相干的数据源,最好用多个事务管理器。机智的Spring的Transactional...

    struts hibernate spring 搞定分布式事务

    服务层代码如下: public class HibernateServerImpl implements HibernateServerInterface { @Resource private OracleDAOInterface HibernateByOracleDAO; @Resource private SQLServerDAOInterface ...

    Spring+3.x企业应用开发实战光盘源码(全)

     第10章:对实际应用中Spring事务管理各种疑难问题进行透彻的剖析,让读者对Spring事务管理不再有云遮雾罩的感觉。  第11章:讲解了如何使用Spring JDBC进行数据访问操作,我们还重点讲述了LOB字段处理、主键产生...

    spring事物和rabbitMQ的例子

    spring的2个数据源的配置,并且每个数据源都配置了事物管理。还有rabbitMQ的发送端代码。本人项目亲自用到的,可以运行。

    Spring小例子项目源码

    项目源码,内有Spring AOP、事务、线程小例子,还有AOP实现原理,动态代理,java多线程

    springMVC+Spring+Mybatis+Maven整合代码案例

    5、测试Spring+mybatis的框架搭建,写单元测试JUnit,测试事务配置等:model--&gt;dao(mapper)--&gt;service--&gt;test 6、映入SpringMVC:配置SpringMVC配置信息。--&gt;配置文件:spring-mvc.xml(扫描controller) 7...

    Spring 2.0 开发参考手册

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.6.1. @Transactional 有关的设置 ...

    Spring事务隔离级别简介及实例解析

    主要介绍了Spring事务隔离级别简介及实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

    jbpm4和spring整合例子

    近期网上有人介绍jBPM4与Spring整合的2种方式,但没有人贴出代码,闲着无聊写了个例子,源码见附件,在WEBLOGIC下运行正常,事务由spring控制http://ip:7001/Spring/helloWorld.do

    spring chm文档

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. ...

    Spring中文帮助文档

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知...

    Spring API

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知...

    spring boot 代码示例

    springboot例子, 包含druid数据源, druid的sql监控, druid过滤, mybatis xml配置, mybatis分页插件, logback日志配置, springboot多环境配置, 发送邮件, AOP拦截, 过滤器 spring拦截器, 全局异常, 统一响应, 自定义...

    陈开雄 Spring+3.x企业应用开发实战光盘源码.zip

     第10章:对实际应用中Spring事务管理各种疑难问题进行透彻的剖析,让读者对Spring事务管理不再有云遮雾罩的感觉。  第11章:讲解了如何使用Spring JDBC进行数据访问操作,我们还重点讲述了LOB字段处理、主键产生...

Global site tag (gtag.js) - Google Analytics