(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声明式事务相关推荐

  1. 为什么spring中的controller跳转出错_你的业务代码中Spring声明式事务处理正确了吗?

    Spring 针对 Java Transaction API (JTA).JDBC.Hibernate 和 Java Persistence API(JPA) 等事务 API,实现了一致的编程模型,而 ...

  2. Spring 声明式事务在业务开发中容易碰到的坑总结

    Spring 声明式事务,在业务开发使用上可能遇到的三类坑,包括: 第一,因为配置不正确,导致方法上的事务没生效.我们务必确认调用 @Transactional 注解标记的方法是 public 的,并 ...

  3. Spring声明式事务管理源码解读之事务提交

    /** *作者:张荣华(ahuaxuan) *2007-06-11 *转载:http://www.iteye.com/wiki/Spring-source/1219-Spring声明式事务管理*源码解 ...

  4. Spring声明式事务管理、事务的传播行为xml配置

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. <tx:method name="insert*" propagat ...

  5. Spring 声明式事务应该怎么学?

    1.引言 Spring 的声明式事务极大地方便了日常的事务相关代码编写,它的设计如此巧妙,以至于在使用中几乎感觉不到它的存在,只需要优雅地加一个 @Transactional 注解,一切就都顺理成章地 ...

  6. java spring 事务_java 事务与spring 声明式事务

    Spring声明式事务让我们从复杂的事务处理中得到解脱.使得我们再也无需要去处理获得连接.关闭连接.事务提交和回滚等这些操作.再也无需要我们在与事务相关的方法中处理大量的try-catch-final ...

  7. 【Spring学习笔记 九】Spring声明式事务管理实现机制

    什么是事务?事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用,关乎数据准确性的地方我们一定要用到事务,防止业务逻辑出错. 什么是事务管理,事务管理对于企业应用而言至 ...

  8. Spring声明式事务配置管理方法

    /*2011年8月28日 10:03:30 by Rush  */ 环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加 ...

  9. Spring声明式事务管理的配置详解

    环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加方法: 点击项目右键->Build Path->Add ...

最新文章

  1. Python3 类和继承和组合
  2. etcd集群部署与遇到的坑(转)
  3. 5行代码可实现5倍Scikit-Learn参数调整的更快速度
  4. 使用 Visual Studio 对源代码文件进行哈希处理以确保文件完整性
  5. 英语数字的 android,英语数字听力学霸APP
  6. post的4个参数和ajaxReturn方法
  7. Windows10安装VMware(图文教程)
  8. [设计模式-结构型]代理模式(Proxy)
  9. 安装一直初始化_win10开机一直卡在正在准备自动修复怎么办
  10. IBM\浪潮\Dell\HP服务器raid(磁盘阵列)配置
  11. sql中的distinct
  12. 阿里云服务器部署ShareLaTex(Overleaf)
  13. WPS宏插件使用教程
  14. 信息系统项目管理师学习笔记13-项目合同管理
  15. 会话技术——Cookie
  16. 情景式领导力学习(2) - 实践案例及思考
  17. 信息系统项目管理师必背核心考点(七十二)V模型
  18. 操作系统简述复习笔记
  19. dblp搜文献时各颜色含义
  20. stm32 + ESP8266 wifi获取网络时间和天气 stm32天气预报

热门文章

  1. 吐槽小程序开发踩过的坑,以及一些解决方法
  2. java常用技术栈,HR的话扎心了
  3. 5-3 最长连续递增子序列 (20分)
  4. 强基计划有计算机专业的学校,强基计划有计算机专业吗?强基计划毕业学生国家怎么安排的?...
  5. css设置鼠标指针光标样式
  6. 浅入 spring ioc 单例容器
  7. 浅析简易网页制作的准备工作
  8. java连接kafka api_Kafka-JavaAPI(Producer And Consumer)
  9. Json解析不允许子类父类变量重名的原因
  10. 关键词 onStart()和onResume()存在的原因(测验篇)两者的区别