Spring 事务管理案例 -----文章写得不错 拿来日后学习使用

 

Spring 事务管理案例

事务管理简介

  Spring 事务管理有两种方式:一种是编程式事务管理,即通过编写代码实现事物管理,包括定义事务的开始,程序正常执行后的事物提交,异常时进行的事务回滚。另一种是基于AOP技术实现的声明式事务管理,其主要思想是将事务管理作为一个“切面”代码单独编写,我们只用关心核心业务逻辑代码,然后通过AOP技术将事务管理的“切面”代码织入到业务类中,声明式事务管理有包括基于AOP方式的事务管理和基于 @Transactional注解方式的事务管理,声明式事务管理极大的简化了编程式事务管理的操作流程,不再需要重复地执行定义事物的开始,程序正常执行后事务提交,异常时进行事物回滚这些繁琐的操作,而基于 @Transactional注解的声明式事务又进一步简化了基于AOP的事务管理,减少了Spring配置代码。

  声明式事务的缺点在于只能作用到方法级别,无法做到像编程式事务那样能控制到代码块级别。

  • 事务传播行为

  事务规则也就是事务传播行为,用于解决业务层方法之间的相互调用的问题题。常见的事物传播行为可分为以下几种:

名称说明
REQUIRED表示当前方法必须运行在一个事物环境中,如果一个现有的事物正在运行,该方法将运行在这个事务中,否则,就要开始一个新的事务
REQUIRESNEW表示当前方法必须运行在自己的事务里
SUPPORTS表示当前方法不需要事务处理环境,但如果有一个事务正在运行的话,则这个方法也可以运行在这个事务中
MANDATORY表示当前方法必须运行在一个事务上下文中,否则就抛出异常
NEVER表示当前方法不应该运行在一个事务上下文中,否则就抛出异常

 

  事务管理的主要任务是事务的创建,事务的回滚和事务的提交,是否需要创建事务及如何创建事务,是由事务传播行为控制的,通常数据的读取可以不需要事务管理,或者可以指定为只读事务,而对于数据的增加,删除和修改操作,则有必要进行事务管理。如果没有指定事务的传播行为,Spring默认采用REQUIRED。


转账案例

转账环境搭建

  • 创建表sql(三个账户,初始化金额都为1000)
CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `money` double DEFAULT NULL,<br> PRIMARY KEY (`id`)<br> ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;<br> INSERT INTO `account` VALUES ('1', 'aaa', '1000');<br> INSERT INTO `account` VALUES ('2', 'bbb', '1000');<br> INSERT INTO `account` VALUES ('3', 'ccc', '1000');<br>
  • 项目所需jar包

 

  因为我的jdk是1.8,如果spring的版本用spring3.X的话,后面会出现参数不匹配异常java.lang.IllegalArgumentException,所以我换成了Spring4。

  • 数据库连接参数

  • 日志文件log4j.properties
log4j.rootLogger=INFO,logfile,stdout
            
#write log into file
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.Threshold=warn
log4j.appender.logfile.File=${webapp.root}\\logs\\Transaction.log
log4j.appender.logfile.DatePattern=.yyyy-MM-dd
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=[Transaction] %d{yyyy-MM-dd HH\:mm\:ss} %X{remoteAddr} %X{remotePort} %m %n


#display in console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold=info
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[Transaction] %d{yyyy-MM-dd HH\:mm\:ss} %X{remoteAddr} %X{remotePort} %m %n

  • 创建业务层接口和实现类
package com.zzh.demo1;

public interface AccountService { /**  *   * @param out  :转出账号  * @param in  :转入账号  * @param money :转账金额  */ public void transfer(String out,String in,Double money); }
package com.zzh.demo1;

public class AccountServiceImpl implements AccountService { //注入DAO类 private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void transfer(String out, String in, Double money) { accountDao.outMoney(out, money); accountDao.inMoney(in, money); } }
  • 创建DAO层接口和实现类
package com.zzh.demo1;

public interface AccountDao { /**  * @param out  :转出账号  * @param money :转出金额  */ public void outMoney(String out,Double money); /**  * @param in  :转入账号  * @param money :转入金额  */ public void inMoney(String in,Double money); }

这里让Dao层实现类继承JdbcDaoSupport,这样一来就可以将JdbcTemplate注入其中,不过我是直接将DataSource连接池注入其中,这时我的DAO实现类就可以创建一个JdbcTemplate,然后操作数据库的相关内容。

package com.zzh.demo1;

import org.springframework.jdbc.core.support.JdbcDaoSupport; /**  * DAO层接口实现类  * 这里使用的是JdbcDaoSupport模板  *  */ public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { @Override public void outMoney(String out, Double money) { String sql = "update account set money = money - ? where name = ?"; this.getJdbcTemplate().update(sql,money,out); } @Override public void inMoney(String in, Double money) { String sql = "update account set money = money + ? where name = ?"; this.getJdbcTemplate().update(sql,money,in); } }

 

  当然也可以不选择让DAO层继承JdbcDaoSupport,而是把JdbcTemplate作为他的属性进行操作,通过setter方法利用JdbcTemplate的构造方法将dataSource传入。

package com.zzh.demo1;

import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class AccountDaoImpl implements AccountDao { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource){ this.jdbcTemplate = new JdbcTemplate(dataSource); } @Override public void outMoney(String out, Double money) { String sql = "update account set money = money - ? where name = ?"; this.jdbcTemplate.update(sql,money,out); } @Override public void inMoney(String in, Double money) { String sql = "update account set money = money + ? where name = ?"; this.jdbcTemplate.update(sql, money,in); } }
  • 配置applicationContext.xml

要将c3p0的连接池注入DAO层实现类中,使其可以创建JdbcTemplate。

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:context="http://www.springframework.org/schema/context"  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.xsd   http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd  http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd  http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 引入外部属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置c3p0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 配置业务层 --> <bean id="accountService" class="com.zzh.demo1.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <!-- 配置DAO层,注入连接池就可以得到jdbc模板--> <bean id="accountDao"

转载于:https://www.cnblogs.com/zhaoyfk/p/8630914.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值