27. 代码实例-spring声明式事务
(1)spring配置文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 3 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" 4 xsi:schemaLocation=" 5 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 6 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 7 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 9 http://www.springframework.org/schema/util classpath:/org/springframework/beans/factory/xml/spring-util-3.0.xsd 10 " 11 default-autowire="byName"> 12 <bean id="paymentSqlSqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> 13 <property name="configLocation" value="classpath:sqlmap/sqlserver/sqlserver-consume.xml" /> 14 <property name="dataSource" ref="paymentSqlDataSource" /> 15 </bean> 16 17 <!-- ============================ payment ======================================= --> 18 <bean id="paymentSqlDataSource" class="org.apache.commons.dbcp.BasicDataSource"> 19 <property name="driverClassName" value="${sqlserver.jdbc.driver}" /> 20 <property name="url" value="${payment.sqlserver.jdbc.url}" /> 21 <property name="username" value="${payment.sqlserver.jdbc.username}" /> 22 <property name="password" value="${payment.sqlserver.jdbc.password}" /> 23 <property name="maxActive" value="30" /> 24 <property name="initialSize" value="2" /> 25 <property name="maxWait" value="60000" /> 26 <property name="maxIdle" value="30" /> 27 <property name="minIdle" value="1" /> 28 <property name="testOnBorrow" value="false"></property> 29 <property name="testWhileIdle" value="true"></property> 30 <property name="validationQuery" value="select 1 "></property> 31 <property name="timeBetweenEvictionRunsMillis"> 32 <value>300000</value> 33 </property> 34 <property name="numTestsPerEvictionRun"> 35 <value>10</value> 36 </property> 37 <property name="minEvictableIdleTimeMillis" value="300000"></property> 38 </bean> 39 <bean id="consumeTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate" > 40 <property name="sqlMapClient" ref="paymentSqlSqlMapClient" /> 41 </bean> 42 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 43 <property name="dataSource" ref="paymentSqlDataSource" /> 44 </bean> 45 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 46 </beans>
(2)事务相关代码
1 package com.jd.consume.service.consume.impl; 2 3 import java.util.List; 4 5 import javax.annotation.Resource; 6 7 import org.apache.commons.collections.CollectionUtils; 8 import org.slf4j.Logger; 9 import org.slf4j.LoggerFactory; 10 import org.springframework.stereotype.Service; 11 import org.springframework.transaction.annotation.Propagation; 12 import org.springframework.transaction.annotation.Transactional; 13 14 import com.jd.consume.dao.ConsumeDao; 15 import com.jd.consume.dao.OrderTaskDao; 16 import com.jd.consume.domain.ConsumeDetail; 17 import com.jd.consume.domain.OrderTask; 18 import com.jd.consume.service.consume.ConsumeChange; 19 20 /** 21 * 消费额度变更服务 22 * @author guanpanpan 23 * 24 */ 25 @Service(value = "consumeChange") 26 @Transactional(value = "transactionManager", readOnly = true) 27 public class ConsumeChangeImpl implements ConsumeChange { 28 protected final static Logger log = LoggerFactory.getLogger(ConsumeChangeImpl.class); 29 @Resource 30 private OrderTaskDao orderTaskDao; 31 @Resource 32 private ConsumeDao consumeDao; 33 public static boolean throwRuntimeExceptionInTransation = false; 34 35 @Transactional(value = "transactionManager", readOnly = false, rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 36 public void addConsumeWithSingleTask(OrderTask orderTask) { 37 ConsumeDetail consumeDetail = orderTask.genAddConsumeDetail(); 38 //防止重复执行,如果存在uuid置状态为11 39 List<ConsumeDetail> consumeDetails = consumeDao.findConsumeDetailsByUuid(consumeDetail.getUuId()); 40 if (CollectionUtils.isNotEmpty(consumeDetails)) { 41 orderTaskDao.updateStatus(orderTask.getId(), OrderTask.SYN_REPEAT, OrderTask.SYN_LOCK); 42 return; 43 } 44 consumeDao.addConsumeDetail(consumeDetail); 45 consumeDao.insertOrUpdateJdConsume(consumeDetail); 46 //设置状态为已处理,如果失败会在回滚中置好状态 47 orderTaskDao.updateStatus(orderTask.getId(), OrderTask.SYN_COMPLETE, OrderTask.SYN_LOCK); 48 if (throwRuntimeExceptionInTransation) { 49 throw new RuntimeException("rollBack in Test"); 50 } 51 } 52 53 @Override 54 @Transactional(value = "transactionManager", readOnly = false, rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 55 public void reduceConsumeWithSingleTask(OrderTask orderTask) { 56 ConsumeDetail consumeDetail = orderTask.genPastConsumeDetail(); 57 //防止重复执行,如果存在uuid置状态为12 58 List<ConsumeDetail> consumeDetails = consumeDao.findConsumeDetailsByUuid(consumeDetail.getUuId()); 59 if (CollectionUtils.isNotEmpty(consumeDetails)) { 60 orderTaskDao.updatePastStatus(orderTask.getId(), OrderTask.PAST_REPEAT, OrderTask.PAST_LOCK); 61 return; 62 } 63 //设置状态为已处理,如果失败会在回滚中置好状态 64 orderTaskDao.updatePastStatus(orderTask.getId(), OrderTask.PAST_DUE_YET, OrderTask.PAST_LOCK); 65 consumeDao.addConsumeDetail(consumeDetail); 66 consumeDao.insertOrUpdateJdConsume(consumeDetail); 67 if (throwRuntimeExceptionInTransation) { 68 throw new RuntimeException("rollBack in Test"); 69 } 70 71 } 72 73 }
(3)编码式事务
有时不能使用声明时事务,比如分库分表。声明式的库是固定的。
1 package com.jd.consume.service.consume.impl; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.annotation.Resource; 7 8 import org.slf4j.Logger; 9 import org.slf4j.LoggerFactory; 10 import org.springframework.jdbc.datasource.DataSourceTransactionManager; 11 import org.springframework.stereotype.Service; 12 import org.springframework.transaction.TransactionDefinition; 13 import org.springframework.transaction.TransactionStatus; 14 import org.springframework.transaction.support.DefaultTransactionDefinition; 15 import org.springframework.util.CollectionUtils; 16 17 import com.jd.consume.dao.moredb.DbManager; 18 import com.jd.consume.dao.mysql.ConsumeDaoMysql; 19 import com.jd.consume.dao.mysql.ConsumeDetailDaoMysql; 20 import com.jd.consume.dao.mysql.OrderTaskDaoMysql; 21 import com.jd.consume.domain.ConsumeDetail; 22 import com.jd.consume.domain.JdConsume; 23 import com.jd.consume.domain.OrderTask; 24 import com.jd.consume.service.consume.CalJdconsume; 25 import com.jd.consume.service.consume.ConsumeChange; 26 import com.jd.consume.util.LogUtil; 27 import com.jd.consume.util.PropertyUtil; 28 29 /** 30 * 消费额度变更服务 31 * @author guanpanpan 32 * 33 */ 34 @Service(value = "consumeChange") 35 //@Transactional(value = "transactionManager", readOnly = true) 36 public class ConsumeChangeImpl implements ConsumeChange { 37 protected final static Logger log = LoggerFactory.getLogger(ConsumeChangeImpl.class); 38 @Resource 39 private OrderTaskDaoMysql orderTaskDaoMysql; 40 @Resource 41 private ConsumeDaoMysql consumeDaoMysql; 42 @Resource 43 private ConsumeDetailDaoMysql consumeDetailDaoMysql; 44 @Resource 45 private DbManager dbManager; 46 @Resource(name = "calJdconsumeFind") 47 private CalJdconsume calJdconsumeFind; 48 @Resource(name = "calJdconsumeCal") 49 private CalJdconsume calJdconsumeCal; 50 private boolean calJdconsumeByFind = PropertyUtil.getBooleanParameter("calJdconsumeByFind");//默认用数据库计算,减少传输 51 public static boolean throwRuntimeExceptionInTransation = false; 52 public static ThreadLocal<Set<String>> reDianPin = new ThreadLocal<Set<String>>();//热点数据 53 public static ThreadLocal<Long> reDianLastTime = new ThreadLocal<Long>();//热点数据 54 public static boolean isReDianFlag = true; 55 public static int reDianExePerTime = 5;//分钟,每几分钟执行一下热点 56 public static int reDianMomeryMax = 100;//最多缓存热点数据 57 public static boolean isUpGrade = false;//是否需要升级,新版本升级程序上线后就不需要再升级了 58 59 //@Transactional(value = "transactionManager", readOnly = false, rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 60 public void addConsumeWithSingleTask(int dbNo, OrderTask orderTask) { 61 //因为分库所以不能用注解 62 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 63 def.setReadOnly(false); 64 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 65 DataSourceTransactionManager transactionManager = dbManager.getTransactionManager(dbNo); 66 TransactionStatus status = transactionManager.getTransaction(def); 67 try { 68 ConsumeDetail consumeDetail = orderTask.genAddConsumeDetail(); 69 //防止重复执行,如果存在uuid置状态为11 70 ConsumeDetail consumeDetailDb = consumeDetailDaoMysql 71 .findConsumeDetailsByUuid(orderTask.getPin(), consumeDetail.getUuId()); 72 if (null != consumeDetailDb) { 73 orderTaskDaoMysql.updateStatus(dbNo, orderTask.getId(), OrderTask.SYN_REPEAT, OrderTask.SYN_LOCK); 74 transactionManager.commit(status); 75 return; 76 } 77 consumeDetailDaoMysql.addConsumeDetail(consumeDetail); 78 if (isReDianFlag) { 79 JdConsume jdConsume = consumeDaoMysql.getJdConsumeByPin(orderTask.getPin()); 80 if (null == jdConsume || !jdConsume.isReDian()) { 81 calAndSaveJdConsumeAmounts(orderTask.getPin());//计算消费额度 82 //设置状态为已处理,如果失败会在回滚中置好状态 83 updateAddStatus(dbNo, orderTask); 84 } else { 85 //加入热点集合去重 86 Set<String> reDianSet = reDianPin.get(); 87 if (reDianSet == null) { 88 reDianSet = new HashSet<String>(); 89 } 90 reDianSet.add(orderTask.getPin()); 91 reDianPin.set(reDianSet); 92 //设置时间 93 if (reDianLastTime.get() == null) { 94 reDianLastTime.set(System.currentTimeMillis()); 95 } 96 //设置状态为已处理,如果失败会在回滚中置好状态 97 orderTaskDaoMysql.updateStatus(dbNo, orderTask.getId(), OrderTask.SYN_REDIAN_ADD, OrderTask.SYN_LOCK); 98 99 } 100 } else { 101 calAndSaveJdConsumeAmounts(orderTask.getPin());//计算消费额度 102 updateAddStatus(dbNo, orderTask); 103 } 104 105 if (throwRuntimeExceptionInTransation) { 106 throw new RuntimeException("rollBack in Test"); 107 } 108 } catch (Exception e) { 109 transactionManager.rollback(status); 110 throw new RuntimeException(e); 111 } 112 transactionManager.commit(status); 113 } 114 115 private void updateAddStatus(int dbNo, OrderTask orderTask) { 116 if (isUpGrade) { 117 orderTaskDaoMysql.updateStatus(dbNo, orderTask.getId(), OrderTask.SYN_COMPLETE, OrderTask.SYN_LOCK); 118 } else { 119 orderTaskDaoMysql.updateStatusNoGrade(dbNo, orderTask.getId(), OrderTask.SYN_COMPLETE, OrderTask.SYN_LOCK); 120 } 121 122 } 123 124 private void updateAddStatusRedian(int dbNo, String pin) { 125 if (isUpGrade) { 126 orderTaskDaoMysql.updateStatus(dbNo, pin, OrderTask.SYN_COMPLETE, OrderTask.SYN_REDIAN_ADD); 127 } else { 128 orderTaskDaoMysql.updateStatusNoGrade(dbNo, pin, OrderTask.SYN_COMPLETE, OrderTask.SYN_REDIAN_ADD); 129 } 130 131 } 132 133 @Override 134 public void dealRedianDatas(int dbNo, int threadId) { 135 Set<String> reDianSet = reDianPin.get(); 136 if (CollectionUtils.isEmpty(reDianSet)) { 137 return; 138 } 139 140 //5分钟执行一次 141 boolean isTime = (System.currentTimeMillis() - reDianLastTime.get()) > 1000 * 60 * reDianExePerTime; 142 if (isTime || reDianSet.size() > reDianMomeryMax) { 143 for (String pin : reDianSet) { 144 calAndSaveJdConsumeAmounts(pin);//计算消费额度 145 updateAddStatusRedian(dbNo, pin); 146 } 147 //重置时间 148 reDianLastTime.set(System.currentTimeMillis()); 149 //重置集合 150 reDianPin.set(new HashSet<String>()); 151 LogUtil.error(LogUtil.ADDCONSUME, "reDian:" + isTime + reDianSet); 152 LogUtil.error(LogUtil.DT, "reDian:" + isTime + "-" + dbNo + "-" + threadId + reDianSet); 153 } 154 } 155 156 @Override 157 public void calAndSaveJdConsumeAmounts(String pin) { 158 JdConsume jdConsume = calJdconsume(pin); 159 consumeDaoMysql.insertOrUpdateJdConsume(jdConsume); 160 } 161 162 @Override 163 public JdConsume calJdconsume(String pin) { 164 if (calJdconsumeByFind) { 165 return calJdconsumeFind.calJdconsume(pin); 166 } else { 167 return calJdconsumeCal.calJdconsume(pin); 168 } 169 170 } 171 172 }
注:1,2代码来源于consume-grade-sql,3来源于consume-grade-final(mysql版本)
转载于:https://www.cnblogs.com/guanpanpan/p/3414560.html
27. 代码实例-spring声明式事务相关推荐
- 为什么spring中的controller跳转出错_你的业务代码中Spring声明式事务处理正确了吗?
Spring 针对 Java Transaction API (JTA).JDBC.Hibernate 和 Java Persistence API(JPA) 等事务 API,实现了一致的编程模型,而 ...
- Spring 声明式事务在业务开发中容易碰到的坑总结
Spring 声明式事务,在业务开发使用上可能遇到的三类坑,包括: 第一,因为配置不正确,导致方法上的事务没生效.我们务必确认调用 @Transactional 注解标记的方法是 public 的,并 ...
- Spring声明式事务管理源码解读之事务提交
/** *作者:张荣华(ahuaxuan) *2007-06-11 *转载:http://www.iteye.com/wiki/Spring-source/1219-Spring声明式事务管理*源码解 ...
- Spring声明式事务管理、事务的传播行为xml配置
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. <tx:method name="insert*" propagat ...
- Spring 声明式事务应该怎么学?
1.引言 Spring 的声明式事务极大地方便了日常的事务相关代码编写,它的设计如此巧妙,以至于在使用中几乎感觉不到它的存在,只需要优雅地加一个 @Transactional 注解,一切就都顺理成章地 ...
- java spring 事务_java 事务与spring 声明式事务
Spring声明式事务让我们从复杂的事务处理中得到解脱.使得我们再也无需要去处理获得连接.关闭连接.事务提交和回滚等这些操作.再也无需要我们在与事务相关的方法中处理大量的try-catch-final ...
- 【Spring学习笔记 九】Spring声明式事务管理实现机制
什么是事务?事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用,关乎数据准确性的地方我们一定要用到事务,防止业务逻辑出错. 什么是事务管理,事务管理对于企业应用而言至 ...
- Spring声明式事务配置管理方法
/*2011年8月28日 10:03:30 by Rush */ 环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加 ...
- Spring声明式事务管理的配置详解
环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加方法: 点击项目右键->Build Path->Add ...
最新文章
- Python3 类和继承和组合
- etcd集群部署与遇到的坑(转)
- 5行代码可实现5倍Scikit-Learn参数调整的更快速度
- 使用 Visual Studio 对源代码文件进行哈希处理以确保文件完整性
- 英语数字的 android,英语数字听力学霸APP
- post的4个参数和ajaxReturn方法
- Windows10安装VMware(图文教程)
- [设计模式-结构型]代理模式(Proxy)
- 安装一直初始化_win10开机一直卡在正在准备自动修复怎么办
- IBM\浪潮\Dell\HP服务器raid(磁盘阵列)配置
- sql中的distinct
- 阿里云服务器部署ShareLaTex(Overleaf)
- WPS宏插件使用教程
- 信息系统项目管理师学习笔记13-项目合同管理
- 会话技术——Cookie
- 情景式领导力学习(2) - 实践案例及思考
- 信息系统项目管理师必背核心考点(七十二)V模型
- 操作系统简述复习笔记
- dblp搜文献时各颜色含义
- stm32 + ESP8266 wifi获取网络时间和天气 stm32天气预报
热门文章
- 吐槽小程序开发踩过的坑,以及一些解决方法
- java常用技术栈,HR的话扎心了
- 5-3 最长连续递增子序列 (20分)
- 强基计划有计算机专业的学校,强基计划有计算机专业吗?强基计划毕业学生国家怎么安排的?...
- css设置鼠标指针光标样式
- 浅入 spring ioc 单例容器
- 浅析简易网页制作的准备工作
- java连接kafka api_Kafka-JavaAPI(Producer And Consumer)
- Json解析不允许子类父类变量重名的原因
- 关键词 onStart()和onResume()存在的原因(测验篇)两者的区别