Spring中的事物管理,用 @Transactional 注解声明式地管理事务
事物:
事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的 完整性和 一致性.
事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
事务的四个关键属性:
原子性:事务是一个原子操作, 由一系列动作组成. 事务的原子性确保动作要么全部完成要么完全不起作用.
一致性:一旦所有事务动作完成, 事务就被提交. 数据和资源就处于一种满足业务规则的一致性状态中.
隔离性:可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏.
持久性:一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中.
-------------------------------------------------------------------
用 @Transactional 注解声明式地管理事务的例子:
在mysql中建立三个数据表分别为:
account:属性:用户名:username(varchar),该用户的账户余额:balance(int);
book:书的编号:isbn(int),书名:book_name(varchar),价钱:price(int);
book_stock:书的编号:isbn(int),库存:stock(int);
导包。。。。
建立存放连接数据库的file文件:jdbc.properties;
jdbc.user=root
jdbc.password=lxn123
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///spring2 jdbc.initPoolSize=5
jdbc.maxPoolSize=10
建立spring bean configuration file的xml文件,导入资源文件和配置c3p0数据源,这是基于注解的声明管理事物,所以也将加特定注解的包进行扫描;
<!-- 基于注解的bean配置,扫描这个包及其自包 -->
<context:component-scan base-package="com.atguigu.spring.jdbc"></context:component-scan> <!-- 导入资源文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置c3p0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
</bean> <!-- 配置spring 的 JdbcTemplate ,里面有一些jdbc的方法,实现对数据库数据的增删改查-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
建立一个接口:让继承他的子类去实例化一些方法
package com.atguigu.spring.jdbc; public interface BookShopDao { //根据书号获取书的单价,isbn为书名的编号
public int findBookPriceByIsbn(int isbn); //更新数的库存. 使书号对应的库存 - 1
public void updateBookStock(int isbn); //更新用户的账户余额: 使 username 的 balance - price
public void updateUserAccount(String username,int price);
}
建立BookShopDaoImpl 类并继承接口: BookShopDao,实例化其方法,并且在类名前 加注解:@Repository("bookShopDao"),和在属性private JdbcTemplate jdbcTemplae;的上边加注解:@Autowired
package com.atguigu.spring.jdbc; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository; @Repository("bookShopDao")
public class BookShopDaoImpl implements BookShopDao { @Autowired
private JdbcTemplate jdbcTemplae; //通过书名获取书的价格
@Override
public int findBookPriceByIsbn(int isbn) {
String sql="select price from book where isbn=?";
return jdbcTemplae.queryForObject(sql, Integer.class, isbn);
} @Override
public void updateBookStock(int isbn) {
String sql="select stock from book_stock where isbn=?";
//stock,指数的库存
//通过书名检查书的库存
int stock=jdbcTemplae.queryForObject(sql, Integer.class, isbn);
if(stock==0){
System.out.println("库存不足!!!");
throw new BookStockException("库存不足!!!");
} String sql2="update book_stock set stock=stock-1 where isbn=?";
jdbcTemplae.update(sql2, isbn);
} //用户的余额减去要购买书的价钱
@Override
public void updateUserAccount(String username, int price) {
//验证余额是否足够, 若不足, 则抛出异常
String sql2="select balance from account where username=?";
int balance=jdbcTemplae.queryForObject(sql2, Integer.class, username);
if(balance<price){
System.out.println("余额不足!!!");
throw new BookStockException("余额不足!!!");
} String sql="update account set balance=balance-? where username=?";
jdbcTemplae.update(sql, price, username);
} }
建立一个接口:BookShopService,有一个没有实例化的方法;
package com.atguigu.spring.jdbc; public interface BookShopService {
public void purchase(String username,int isbn);
}
建立类: BookShopServiceImpl 继承于接口 BookShopService,有一个方法,合并了BookShopDaoImpl类中的三个方法,建立了一个“事物”;在该类上边加了注解@Service("bookShopService"),在属性private BookShopDao bookShopDao;加了注解@Autowired,在其方法上加了注解@Transactional(propagation=Propagation.REQUIRES_NEW),都是便于在spring的xml文件中bean的配置扫描识别;
package com.atguigu.spring.jdbc; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; @Service("bookShopService")
public class BookShopServiceImpl implements BookShopService { @Autowired
private BookShopDao bookShopDao;
/**
*添加事务注解
*1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时
*如何使用事务, 默认取值为 REQUIRED, 即使用调用方法的事务
*REQUIRES_NEW: 事务自己的事务, 调用的事务方法的事务被挂起.
*2.使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED
*3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚. 也可以通过对应的
*属性进行设置. 通常情况下去默认值即可.
*4.使用 readOnly 指定事务是否为只读. 表示这个事务只读取数据但不更新数据,
*这样可以帮助数据库引擎优化事务. 若真的事一个只读取数据库值的方法, 应设置 readOnly=true
*5.使用 timeout 指定强制回滚之前事务可以占用的时间.
*@Transactional(propagation=Propagation.REQUIRES_NEW,
isolation=Isolation.READ_COMMITTED,
noRollbackFor={UserAccountException.class},
readOnly=false,
timeout=3)
*
*/
@Transactional(propagation=Propagation.REQUIRES_NEW)
@Override
public void purchase(String username, int isbn) { //1. 获取书的单价
int price=bookShopDao.findBookPriceByIsbn(isbn); //2. 更新书的库存
bookShopDao.updateBookStock(isbn); //3. 更新用户余额
bookShopDao.updateUserAccount(username, price);
} }
建立一个接口:Cashier
package com.atguigu.spring.jdbc; import java.util.List; public interface Cashier {
//购买多本书
public void checkout(String username,List<Integer> isbns);
}
建立类:CashierImpl 继承于上边的接口 Cashier,该中有private BookShopService bookShopService这个“事物”父类的属性,类中仅有的一个方法,可以实现多个“原子事物",该类是调用事物的事物类,仅有的方法为调用事物的事物方法;在该类上边加注解@Service("cashier"),在属性private BookShopService bookShopService;上边加注解@Autowired,在方法上边加事物的注解@Transactional
package com.atguigu.spring.jdbc; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("cashier")
public class CashierImpl implements Cashier { @Autowired
private BookShopService bookShopService; @Transactional
@Override
public void checkout(String username, List<Integer> isbns) {
for(int isbn:isbns){
bookShopService.purchase(username, isbn);
} } }
在spring的xml文件中 配置事物管理器和 启用事物管理器的注解
<!-- 配置事物管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 启用事物管理器的注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
最后建立测试类:JUnitTest
package com.atguigu.spring.jdbc; import java.sql.SQLException;
import java.util.Arrays; import javax.sql.DataSource; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate; public class JUnitTest { private ApplicationContext ctx=null;
private BookShopService bookShopService;
private Cashier cashier;
{
ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
bookShopService=(BookShopService) ctx.getBean("bookShopService");
cashier=(Cashier) ctx.getBean("cashier");
} @Test
//调用事物的事物方法的测试,即有多个事物
public void testCashier(){
cashier.checkout("AA", Arrays.asList(1001,1002));
}
@Test
//事物的测试方法
public void testPurchase(){
bookShopService.purchase("AA", 1001);
}
//测试数据库连接池是否连接成功
public void testDataSource() throws SQLException {
DataSource dataSource=(DataSource) ctx.getBean("dataSource");
System.out.println(dataSource.getConnection()); } }
建立一个异常处理类:BookStockException 继承于异常处理父类 RuntimeException
package com.atguigu.spring.jdbc; public class BookStockException extends RuntimeException {
//异常类的建立:继承于RuntimeException这个父类,点击上边的Source,设置构造器,即可
public BookStockException() {
super();
// TODO Auto-generated constructor stub
} public BookStockException(String arg0, Throwable arg1, boolean arg2,
boolean arg3) {
super(arg0, arg1, arg2, arg3);
// TODO Auto-generated constructor stub
} public BookStockException(String arg0, Throwable arg1) {
super(arg0, arg1);
// TODO Auto-generated constructor stub
} public BookStockException(String arg0) {
super(arg0);
// TODO Auto-generated constructor stub
} public BookStockException(Throwable arg0) {
super(arg0);
// TODO Auto-generated constructor stub
} }
Spring中的事物管理,用 @Transactional 注解声明式地管理事务的更多相关文章
- Spring中的事物管理----HelloWorld
在学习Spring的事物管理之前明白先明白几个概念1什么是事物:事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用例子说明:例如银行转账,A账户转账(转2 ...
- 9.spring:事务管理(下):声明式事务管理
声明式事务管理 sprin的声明式事务是管理AOP技术实现的事务管理,其本质是是对方法前后进行拦截,然后 在目标方法开始之前创建或者加入一个事务,在执行完成目标方法之后根据执行情况提交或者回滚事务. ...
- Spring声明式事务管理基于@Transactional注解
概述:我们已知道Spring声明式事务管理有两种常用的方式,一种是基于tx/aop命名空间的xml配置文件,另一种则是基于@Transactional 注解. 第一种方式我已在上文为大 ...
- 解析Spring第四天(Spring中的事物、Spring框架来管理模板类)
JDBC模板技术: Spring框架中提供了很多持久层的模板类来简化编程,使用模板类编写程序会变的简单 template 模板 都是Spring框架提供XxxTemplate 提供了JDBC模板,Sp ...
- Spring事务的介绍,以及基于注解@Transactional的声明式事务
前言 事务是一个非常重要的知识点,前面的文章已经有介绍了关于SpringAOP代理的实现过程:事务管理也是AOP的一个重要的功能. 事务的基本介绍 数据库事务特性: 原子性 一致性 隔离性 持久性 事 ...
- Spring中@Autowired、@Resource和@Inject注解的使用和区别
在使用Spring进行项目开发的时候,会大量使用到自动装配,那自动装配是什么呢?简单来说:Spring 利用依赖注入(DI)功能,完成SpringIOC容器中各个组件之间的依赖关系赋值管理. 下面介绍 ...
- Spring事务管理者与Spring事务注解--声明式事务
1.在Spring的applicationContext.xml中配置事务管理者 PS:具体的说明请看代码中的注释 Xml代码: <!-- 声明式事务管理的配置 --> <!-- 添 ...
- 重新学习Spring注解——声明式事务
36.声明式事务-环境搭建 37.声明式事务-测试成功 38.[源码]-声明式事务-源码分析 /** * 声明式事务: * * 环境搭建: * 1.导入相关依赖 * 数据源.数据库驱动.Spring- ...
- Spring Cloud 入门Eureka -Consumer服务消费(声明式Feign)(三)
Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端.它使得编写Web服务客户端变得更加简单.我们只需要通过创建接口并用注解来配置它既可完成对Web服务接 ...
随机推荐
- vmware启动虚拟机报“内部错误”的解决方法
最近换了Win8系统,结果vmware就报了如标题描述的错误,网上查了些资料,现将解决方法记录在此,以备查阅. 右键点击wmware程序图标,选择[属性],选择[兼容性]选项卡,勾选“以管理员身份运行 ...
- Jackson转换对象为json的时候报java.lang.stackoverflowerror
无论在将一个对象转为json字符串的时候采用何种算法,如果你的对象的属性的类型不是基本类型或对应的引用类型,转换应该都不会就此结束,那么有一种方式可以导致这种转换陷入无限循环:将某个对象的属性设为对象 ...
- thinkphp的field方法的用法
ThinkPHP的连贯操作方法中field方法有很多的使用技巧,field方法主要目的是标识要返回或者操作的字段. 1.用于查询 在查询操作中field方法是使用最频繁的. $Model->fi ...
- matplotlib 安装与使用
1.在ubuntu下输入 sudo apt-get install python-matplotlib 安装matplotlib 2.简单代码使用
- php课程---Ajax(老师详解)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Ubuntu Linux上安装配置Mysql
一.安装: 三种安装方式: 1. 从网上安装 sudo apt-get install mysql-server.装完已经自动配置好环境变量,可以直接使用mysql的命令. 注:建议将/etc/apt ...
- Matlab图像处理函数:regionprops
本篇文章为转载,仅为方便学术讨论所用,不用于商业用途.由于时间较久,原作者以及原始链接暂时无法找到,如有侵权以及其他任何事宜欢迎跟我联系,如有侵扰,在此提前表示歉意.----------------- ...
- 10.5.2 Boot Block 启动块 - 操作系统教程
简单一篇文章明白地讲解了计算机操作系统的启动过程 OPERATING SYSTEM CONCEPTS ABRAHAM SILBERSCHATZ PETER BAER GALVIN GREG GAGNE ...
- web.xml配置error-page
一. 通过错误码来配置error-page <error-page> <error-code>404</error-code> <location>/e ...
- 能套用的tab栏切换
效果: 在style.js文件里封装了一个Show函数,有4个参数,di(当前点击的按钮),num(按钮个数,也可以说是下面具体内容个数),divn(一个id前缀,这个例子里是ta,),active( ...