自定义事务管理器TransactionManager对象
自定义事务管理器TransactionManager对象
以aop思想,实现事务管理切面
1. DataSource注册容器
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启包扫描注解--><context:component-scan base-package="com.hang"/><!--导入jdbc.properties文件--><context:property-placeholder location="classpath:jdbc.properties"/><!--配置druid数据库连接池--><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="url" value="${jdbc.url}"/><property name="driverClassName" value="${jdbc.driver}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="initialSize" value="${jdbc.initialSize}"/></bean><!--开启aop注解--><aop:aspectj-autoproxy/>
</beans>
2. 定义事务管理器MyTransactionManager对象
定义事务管理器MyTransactionManager对象,注册进spring容器。(依赖Druid连接池,获取连接,开始事务,提交事务,回滚事务,关闭连接)
@Component
public class MyTransactionManager {@Autowiredprivate DataSource dataSource;// 获取连接public Connection getConnection(){Connection conn = null;try {conn = dataSource.getConnection();ConnUtil.setConn(conn);} catch (SQLException e) {e.printStackTrace();}return conn;}// 开始事务public void openTransaction(){try {ConnUtil.getConn().setAutoCommit(false);} catch (SQLException e) {e.printStackTrace();}}// 提交事务public void openCommit(){try {ConnUtil.getConn().commit();} catch (SQLException e) {e.printStackTrace();}}// 回滚事务public void openRollback(){try {ConnUtil.getConn().rollback();} catch (SQLException e) {e.printStackTrace();}}// 关闭连接public void closeConnection(){Connection conn = ConnUtil.getConn();try {if (conn!=null){conn.close();}} catch (SQLException e) {e.printStackTrace();}}public DataSource getDataSource() {return dataSource;}public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}
}
3. 定义dao接口
定义dao接口,使用jdbc定义dao实现,不要使用mybatis,把dao实现注册spring容器(curd)
public interface SysUserDao {SysUser queryById(Integer id) throws Exception;Integer insert(SysUser sysUser) throws Exception;int update(SysUser sysUser);int deleteById(Long id);
}
@Repository
public class SysUserDaoImpl implements SysUserDao {private Connection conn = null;private ResultSet rs = null;private PreparedStatement ps = null;@Overridepublic SysUser queryById(Integer id) throws Exception {SysUser sysUser = null;conn = ConnUtil.getConn();ps = conn.prepareStatement("select * from db_stage_three.sys_user where id = ?");ps.setInt(1, id);rs = ps.executeQuery();if (rs.next()) {sysUser = new SysUser();sysUser.setUname("hello");}return sysUser;}@Overridepublic Integer insert(SysUser sysUser) throws Exception {Integer result = null;conn = ConnUtil.getConn();ps = conn.prepareStatement("insert into db_stage_three.sys_user ( uname, uphone, upwd, uwechat, uemail, role_id, dept_id) values (?,?,?,?,?,?,?)");ps.setString(1, sysUser.getUname());ps.setString(2, sysUser.getUphone());ps.setString(3, sysUser.getUpwd());ps.setString(4, sysUser.getUwechat());ps.setString(5, sysUser.getUemail());ps.setInt(6, sysUser.getRoleId());ps.setInt(7, sysUser.getDeptId());result = ps.executeUpdate();return result;}@Overridepublic int update(SysUser sysUser) {return 0;}@Overridepublic int deleteById(Long id) {return 0;}}
4. 定义service接口
定义service接口,定义service实现,注册容器(curd)。
public interface SysUserService {SysUser queryById(Integer id);SysUser insert(SysUser sysUser);
}
@Service()
public class SysUserServiceImpl implements SysUserService {@Resourceprivate SysUserDao sysUserDao;@Overridepublic SysUser queryById(Integer id) {Connection conn = null;// 织入获取连接,开始事务,提交事务,回滚事务,关闭连接SysUser sysUser = null;try {sysUser = this.sysUserDao.queryById(id);} catch (Exception e) {e.printStackTrace();}return sysUser;}@Transaction // 使用基于自定义注解方式定义切入点表达式@Overridepublic SysUser insert(SysUser sysUser) {try {this.sysUserDao.insert(sysUser);} catch (Exception e) {e.printStackTrace();}int i = 1/0;return sysUser;}}
自定义注解代码如下:
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Transaction {}
5. 定义事务切面(依赖MyTransactionManag)
定义事务切面(依赖MyTransactionManag),定义环绕通知,织入到service层的数据库操作方法,执行方法之前打开事务,异常回滚,方法返回提交事务,最终关闭连接。定义 ServiceTransAspect 类作为切面
@Component
@Aspect
public class ServiceTransAspect {@Autowiredprivate MyTransactionManager transactionManager;// 基于 AspectJ 的切入点表达式@Pointcut("execution(* com.hang.service.impl.SysUserServiceImpl.*(..))")public void servicePointCut() {}// 后置通知关闭数据库连接对象@After("servicePointCut()")public void closeConnection(){Connection conn = ConnUtil.getConn();if (conn!=null){try {conn.close();ConnUtil.clear();conn = null;} catch (SQLException e) {e.printStackTrace();}}}// 基于自定义注解形式@Pointcut("@annotation(com.hang.aspect.Transaction)")public void annotationPointCut() {}// 环绕通知 实现事务的开启、回滚、提交和连接对象的关闭@Around(value = "annotationPointCut()")public Object serviceManage(ProceedingJoinPoint pjp) {Object result = null;try {transactionManager.getConnection();transactionManager.openTransaction();result = pjp.proceed();transactionManager.openCommit();} catch (Throwable throwable) {transactionManager.openRollback();throwable.printStackTrace();} finally {transactionManager.closeConnection();}return result;}}
6. 自定义工具类
在并发环境下,如果没使用ThreadLocal类维护线程内部的局部变量Connection(单Connection对象),两个线程共同访问一个公共变量。例如A用户获取数据库连接对象,并将Connection对象占为己有,对数据进行操作时,B用户也获取到数据库连接对象,获取Connection对象,此时A不具有Connection对象,B用户完成事务提交关闭连接,此时Connection对象为null,A用户数据则会提交失败。
ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量。
对ThreadLocal作用的总结:
- 线程并发: 在多线程并发的场景下
- 传递数据: 我们可以通过ThreadLocal在同一线程,不同组件中传递公共变量
- 线程隔离: 每个线程的变量都是独立的,不会互相影响
@Component
public class ConnUtil {private static ThreadLocal<Connection> threadLocalConn = new ThreadLocal<>();@Resourceprivate MyTransactionManager tm;private static MyTransactionManager manager;public static void clear() {threadLocalConn.remove();}@PostConstructpublic void setTransactionManager(){manager = tm;}public static Connection getConn() {Connection connection = threadLocalConn.get();if (connection!=null){return connection;}else {return manager.getConnection();}}public static void setConn(Connection conn) {threadLocalConn.set(conn);}
}
自定义事务管理器TransactionManager对象相关推荐
- 事务管理自定义事务管理器
事务管理自定义事务管理器 public class DBUtils {//获取链接//在当前线程中存储所使用的链接private ThreadLocal<Connection> threa ...
- Spring AOP事务实现原理之事务管理器TransactionManager
流程图 该图介绍了事务的传播行为 该流通图展示的是TransactionManager具体如何结合事务的传播行为进行事务获取 该流通图展示的是TransactionManager具体如何结合事务的传播 ...
- mybatis plus 事务管理器_学习MyBatis 框架
1. 框架是什么? a 框架就就是写好的功能架构 一些重复的代码的深度的封装 b 框架也是一个半成品 调用同时 也需要告诉框架一些信息 c一般以配置文件方式告知框架 多数会使用Xml作为框架的配置文件 ...
- spring(三)之事务、事务管理器(TransactionManager)简介及实现事务的4种方式
1.事务 一组业务ACID操作,要么全部成功,要么全部不成功. 事务特性:①原子性,针对整体而言(一个事务不可以被拆分):②一致性,针对数据而言(一个事务执行之前和执行之后必须处于一致性状态,一个事务 ...
- mybatis源码分析之事务管理器
2019独角兽企业重金招聘Python工程师标准>>> 上一篇:mybatis源码分析之Configuration 主要分析了构建SqlSessionFactory的过程中配置文件的 ...
- mybatis plus 事务管理器_Mybatis中的事务
Mybatis中的事务 数据库中的事务可以保证在连续执行的多条写操作(增删改)时,这多条操作要么成功,要么全部失败,以保证数据和逻辑的完整及严谨 在使用mybatis时,无需考虑事务如何创建,如何提交 ...
- Aop事务小结(事务管理器和自身构建)
声明市事务是利用AOP来实现的. 1.采用事务管理器AOP: <!--3.配置事务切面:控制住连接池 --><bean id="transactionManager&quo ...
- Spring事务管理器分类
Spring并不直接管理事务,事实上,它是提供事务的多方选择.你能委托事务的职责给一个特定的平台实现,比如用JTA或者是别的持久机制.Spring的事务管理器可以用下表表示: 事务管理器的实例 目标 ...
- spring的annotation-driven配置事务管理器详解
来源:http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html 这篇文章是我从ITeye上复制来的,看了一遍,觉得很深刻,决定把他复制来,对原作者表示感 ...
最新文章
- Python:urllib2模块的基本使用
- 【基本操作】主席数统计区间不同颜色个数
- 实现apply call 方法
- 码农的祖宗是个妹子?!信不信由你!
- 继承单例模式 php_详解PHP单例模式之继承碰见的问题
- FGPA 双向 IO 自动方向控制
- Android中代码运行指定的Apk
- 基本概念/MM相关概念
- Linux安装Elasticsearch+Kibana(7.10.2)
- [转] CMake入门
- how to make Membership header extension fields editable
- loadrunner发送json_Loadrunner接口测试-发送JSON格式的请求
- vue项目的骨架及常用组件介绍
- 随机森林、gbdt算法
- WebSocket 时时双向数据,前后端(聊天室)
- java抽象工厂模式_java简单工厂模式和抽象工厂模式
- 多媒体计算机音频怎么连接,解决电脑连多媒体为什么没有声音
- 脑肿瘤分割论文打卡2:E1D3 U-Net for Brain Tumor Segmentation
- Elasticsearch顶尖高手系列:高手进阶篇(二)
- php电子邮件群发源码,php电子邮件群发源码
热门文章
- STP——RSTP快生成树协议讲解
- c语言file函数头文件,文件操作函数 C语言 (FILE fputc fgetc fputs fgets fsca...
- 比害时新己50米地面蹦极交吻(组图)
- 长沙python哪个培训好
- Fiddler之日常使用简介
- Lisa Lambert:英特尔投资将加大AppUp和Tizen力度
- 计算机启动通常有热启动,计算机的启动通常有哪些三种方法?
- 苹果开发者证书,唯一标识和配置文件的作用及使用
- 2019年09月11日星期三 恒指/美原油/美黄金 走势分析
- js 简单实现 弹出确认 取消对话框