为什么加个注解@Transtaional就可以保证事务的一致性和完整性?

  <!-- 引入属性文件 -->
  
  <context:property-placeholder location="db.properties"/>
  
  <!-- 创建数据源 -->
  
  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
  
  <property name="driverClassName" value="${jdbc.driver}"></property>
  
  <property name="url" value="${jdbc.url}"></property>
  
  <property name="username" value="${jdbc.username}"></property>
  
  <property name="password" value="${jdbc.password}"></property>
  
  </bean>
  
  <!-- 通过数据源配置JdbcTemplate -->
  
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  
  <property name="dataSource" ref="dataSource"></property>
  
  </bean>
  
  <!-- 配置事务管理器,不管是用注解方式或xml方式配置事务,一定要有DataSourceTransactionManager事务管理器的支持 -->
  
  <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  
  <property name="dataSource" ref="dataSource"></property>
  
  </bean>
  
  <!-- 配置事务通知 -->
  
  <tx:advice id="tx" transaction-manager="dataSourceTransactionManager">
  
  <tx:attributes>
  
  <!-- 在设置好的切入点表达式下再次进行事务设置 -->
  
  <tx:method name="buyBook"/>
  
  <tx:method name="checkOut"/>
  
  <!-- 只有select开头的方法才会被事务处理 -->
  
  <tx:method name="select*" read-only="true"/>
  
  <tx:method name="insert*"/>
  
  <tx:method name="update*"/>
  
  <tx:method name="delete*"/>
  
  <tx:method name="*"/>
  
  </tx:attributes>
  
  </tx:advice>
  
  <!-- 配置切入点表达式 -->
  
  <aop:config>
  
  <aop:pointcut expression="execution(* com.atguigu.book_xml.service.impl.*.*(..))" id="pointCut"/>
  
  <aop:advisor advice-ref="tx" pointcut-ref="pointCut"/>
  
  </aop:config>
  
  </beans>
  
  在xml里面定义了数据源bean,数据源bean又被事务管理器bean锁依赖,这时候用的数据源连接对象connection就是同一个,spring管理对象默认为单例
  
  package com.atguigu.book.controller;
  
  import java.util.ArrayList;
  
  import java.util.List;
  
  import org.springframework.beans.factory.annotation.Autowired;
  
  import org.springframework.stereotype.Controller;
  
  import com.atguigu.book.service.BookService;
  
  import com.atguigu.book.service.Cashier;
  
  @Controller
  
  public class BookController {
  
  @Autowired
  
  private BookService service;
  
  @Autowired
  
  private Cashier cashier;
  
  public void buyBook() {
  
  service.buyBook("1", "1001");
  
  }
  
  public void checkOut() {
  
  List<String> bids = new ArrayList<>();
  
  bids.add("1");
  
  bids.add("2");
  
  cashier.checkOut("1001", bids);
  
  }
  
  }
  
  package com.atguigu.book.service.impl;
  
  import java.util.List;
  
  import org.springframework.beans.factory.annotation.Autowired;
  
  import org.springframework.stereotype.Service;
  
  import org.springframework.transaction.annotation.Transactional;
  
  import com.atguigu.book.service.BookService;
  
  import com.atguigu.book.service.Cashier;
  
  @Service
  
  @Transactional
  
  public class CashierServiceImpl implements Cashier {
  
  @Autowired
  
  private BookService service;
  
  @Override
  
  public void checkOut(String uid, List<String> bids) {
  
  for (String bid : bids) {
  
  service.buyBook(bid, uid);
  
  }
  
  }
  
  <?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.5iyouxue.com /schema/beans/spring-beans.xsd
  
  http://www.springframework.org/schema/context http://www.oushengyuL.cn /schema/context/spring-context-4.0.xsd
  
  http://www.springframework.org/schema/aop http://www.changjianyL.cn /schema/aop/spring-aop-4.0.xsd
  
  http://www.springframework.org/schema/tx http://www.huangzuyuL.cn schema/tx/spring-tx-4.0.xsd">
  
  <context:component-scan base-package="com.atguigu.book_xml"></context:component-scan>
  
  System类包含一些有用的字段和方法,他不能被实例化
  
  //用于垃圾回收
  
  public static void gc()
  
  //终止正在运行的java虚拟机。参数用作状态码,根据惯例,非0表示异常终止
  
  public static void exit(int status)
  
  //System.out.println(System.currentTimeMillis());
  
  //返回从1970年1月1日到现在时间的毫秒数(协调时间)
  
  public static currentTimeMills(www.chengsyl.cn)
  
  public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
  
  //src - 源数组。
  
  //srcPos - 源数组中的起始位置。
  
  //dest - 目标数组。
  
  //destPos - 目的地数据中的起始位置。
  
  //length - 要复制的数组元素的数量。
  
  arraycopy方法的使用案例
  
  int[] arr = {11, 22, 33, 44, 55};
  
  int[] arr2 = {6, 7, 8, ,9 ,10};
  
  System.arraycopy(arr, 1, arr2, 2, 2);
  
  System.out.println(Arrays.toString(arr));
  
  System.out.println(Arrays.toString(arr2));
  
  //运行结果
  
  [11, 22, 33, 44, 55]
  
  [6, 7, 22, 33, 10]
  
  currentTimeMills()使用案例
  
  package cn.bwh_www.jinLiyLd.cn2_currenTimeMillis;
  
  public class SystemDemo {
  
  public static void main(String[] args) {
  
  //统计这段程序运行时间
  
  long start = System.currentTimeMillis();
  
  for (int x = 0; x www.chaoylgw.cn/< 10000; x++){
  
  System.out.println("Hello" + x);
  
  }
  
  long end = System.currentTimeMillis();
  
  System.out.println("共耗时" + (end - start) + "毫秒");
  
  }
  
  }
  
  //运行结果
  
  Hello9997
  
  Hello9998
  
  Hello9999
  
  共耗时79毫秒
  
  System.gc() 可用于垃圾回收.当使用System.gc() 回收某个对象所占用的内存之前,通过要求程序调用适当的方法来清理资源,在没有明确指定资源清理的情况下,Java提高了默认机制来清理该对象的资源,就是调用object类的finalize()方法,finalize()方法的作用是释放一个对象占用的内存空间时会被JVM调用.而子类重写该方法, 就可以清理对象占用的资源,该方法没有链式调用, 所以必须手动实现。
  
  从程序结果上可以发现执行system.gc() 前系统会自动调用finalize() 方法清除对象占有的资源。通过super.finalize()可以实现从下到上的方法调用,即先释放自己的资源,再释放父类的资源。
  
  但是不要在程序中频繁的调用垃圾回收,因为每一次执行垃圾回收jvm都会强制启动垃圾回收器运行,就会耗费更多的系统资源会与正常的Java程序运行争抢资源,只有在执行大量的对象的释放才调用垃圾回收最好。
  
  package com.atguigu.book.service.impl;
  
  import org.springframework.beans.factory.annotation.Autowired;
  
  import org.springframework.stereotype.Service;
  
  import org.springframework.transaction.annotation.Isolation;
  
  import org.springframework.transaction.annotation.Propagation;
  
  import org.springframework.transaction.annotation.Transactional;
  
  import com.atguigu.book.dao.BookDao;
  
  import com.atguigu.book.exception.MyException;
  
  import com.atguigu.book.service.BookService;
  
  @Service
  
  //@Transactional
  
  public class BookServiceImpl implements BookService {
  
  @Autowired
  
  private BookDao dao;
  
  /**
  
  * @Transactional:对方法中所有的操作作为一个事务进行管理
  
  * 在方法上使用,只对方法有效果
  
  * 在类上使用,对类中所有的方法都有效果
  
  * @Transactional中可以设置的属性:
  
  *
  
  * propagation:A方法和B方法都有事务,当A在调用B时,会将A中的事务传播给B方法,B方法对于事务的处理方式就是事务的传播行为
  
  * Propagation.REQUIRED:必须使用调用者的事务
  
  * Propagation.REQUIRES_NEW:将调用者的事务挂起,不使用调用者的事务,使用新的事务进行处理
  
  *
  
  * isolation:事务的隔离级别,在并发的情况下,操作数据的一种规定
  
  * 读未提交:脏读 1
  
  * 读已提交:不可重复读 2
  
  * 可重复读:幻读 4
  
  * 串行化:性能低,消耗大 8
  
  *
  
  *
  
  * timeout:在事务强制回滚前最多可以执行(等待)的时间
  
  *
  
  * readOnly:指定当前事务中的一系列的操作是否为只读
  
  * 若设置为只读,不管事务中有没有写的操作,mysql都会在请求访问数据的时候,不加锁,提高性能
  
  * 但是如果有写操作的情况,建议一定不能设置只读
  
  *
  
  * rollbackFor|rollbackForClassName|noRollbackFor|noRollbackForClassName:设置事务回滚的条件
  
  */
  
  @Transactional(propagation=Propagation.REQUIRES_NEW, timeout=3, noRollbackFor= {NullPointerException.class, MyException.class})
  
  public void buyBook(String bid, String uid) {
  
  /*try {
  
  Thread.sleep(5000);
  
  } catch (InterruptedException e) {
  
  // TODO Auto-generated catch block
  
  e.printStackTrace(www.feishenbo.cn);
  
  }*/
  
  Integer price = dao.selectPrice(bid);
  
  dao.updateSt(bid);
  
  dao.updateBalance(uid, price);
  
  }
  
  }
  
  package com.atguigu.book.dao.impl;
  
  import org.springframework.beans.factory.annotation.Autowired;
  
  import org.springframework.jdbc.core.JdbcTemplate;
  
  import org.springframework.stereotype.Repository;
  
  import com.atguigu.book.dao.BookDao;
  
  import com.atguigu.book.exception.MyException;
  
  @Repository
  
  public class BookDaoImpl implements BookDao {
  
  @Autowired
  
  private JdbcTemplate jdbcTemplate;
  
  @Override
  
  public Integer selectPrice(String bid) {
  
  Integer price = jdbcTemplate.queryForObject("select price from book where bid = ?", new Object[] {bid}, Integer.class);
  
  return price;
  
  }
  
  @Override
  
  public void updateSt(String bid) {
  
  //获取该书籍的库存
  
  Integer st = jdbcTemplate.queryForObject("select st from stock where sid = ?", new Object[] {bid}, Integer.class);
  
  if(st <= 0) {
  
  throw new RuntimeException();
  
  }else {
  
  jdbcTemplate.update("update stock set st = st -1 where sid = ?", bid);
  
  }
  
  }
  
  @Override
  
  public void updateBalance(String uid, Integer price) {
  
  Integer balance = jdbcTemplate.queryForObject("select balance from money where uid = ?", new Object[] {uid}, Integer.class);
  
  if(balance < price) {
  
  throw new MyException("余额不足");
  
  }else {
  
  jdbcTemplate.update("update money set balance = balance - ? where uid = ?", price, uid);

猜你喜欢

转载自www.cnblogs.com/qwangxiao/p/11030133.html
今日推荐