自定义事务管理器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作用的总结:

  1. 线程并发: 在多线程并发的场景下
  2. 传递数据: 我们可以通过ThreadLocal在同一线程,不同组件中传递公共变量
  3. 线程隔离: 每个线程的变量都是独立的,不会互相影响
@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对象相关推荐

  1. 事务管理自定义事务管理器

    事务管理自定义事务管理器 public class DBUtils {//获取链接//在当前线程中存储所使用的链接private ThreadLocal<Connection> threa ...

  2. Spring AOP事务实现原理之事务管理器TransactionManager

    流程图 该图介绍了事务的传播行为 该流通图展示的是TransactionManager具体如何结合事务的传播行为进行事务获取 该流通图展示的是TransactionManager具体如何结合事务的传播 ...

  3. mybatis plus 事务管理器_学习MyBatis 框架

    1. 框架是什么? a 框架就就是写好的功能架构 一些重复的代码的深度的封装 b 框架也是一个半成品 调用同时 也需要告诉框架一些信息 c一般以配置文件方式告知框架 多数会使用Xml作为框架的配置文件 ...

  4. spring(三)之事务、事务管理器(TransactionManager)简介及实现事务的4种方式

    1.事务 一组业务ACID操作,要么全部成功,要么全部不成功. 事务特性:①原子性,针对整体而言(一个事务不可以被拆分):②一致性,针对数据而言(一个事务执行之前和执行之后必须处于一致性状态,一个事务 ...

  5. mybatis源码分析之事务管理器

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇:mybatis源码分析之Configuration 主要分析了构建SqlSessionFactory的过程中配置文件的 ...

  6. mybatis plus 事务管理器_Mybatis中的事务

    Mybatis中的事务 数据库中的事务可以保证在连续执行的多条写操作(增删改)时,这多条操作要么成功,要么全部失败,以保证数据和逻辑的完整及严谨 在使用mybatis时,无需考虑事务如何创建,如何提交 ...

  7. Aop事务小结(事务管理器和自身构建)

    声明市事务是利用AOP来实现的. 1.采用事务管理器AOP: <!--3.配置事务切面:控制住连接池 --><bean id="transactionManager&quo ...

  8. Spring事务管理器分类

    Spring并不直接管理事务,事实上,它是提供事务的多方选择.你能委托事务的职责给一个特定的平台实现,比如用JTA或者是别的持久机制.Spring的事务管理器可以用下表表示: 事务管理器的实例 目标 ...

  9. spring的annotation-driven配置事务管理器详解

    来源:http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html 这篇文章是我从ITeye上复制来的,看了一遍,觉得很深刻,决定把他复制来,对原作者表示感 ...

最新文章

  1. Python:urllib2模块的基本使用
  2. 【基本操作】主席数统计区间不同颜色个数
  3. 实现apply call 方法
  4. 码农的祖宗是个妹子?!信不信由你!
  5. 继承单例模式 php_详解PHP单例模式之继承碰见的问题
  6. FGPA 双向 IO 自动方向控制
  7. Android中代码运行指定的Apk
  8. 基本概念/MM相关概念
  9. Linux安装Elasticsearch+Kibana(7.10.2)
  10. [转] CMake入门
  11. how to make Membership header extension fields editable
  12. loadrunner发送json_Loadrunner接口测试-发送JSON格式的请求
  13. vue项目的骨架及常用组件介绍
  14. 随机森林、gbdt算法
  15. WebSocket 时时双向数据,前后端(聊天室)
  16. java抽象工厂模式_java简单工厂模式和抽象工厂模式
  17. 多媒体计算机音频怎么连接,解决电脑连多媒体为什么没有声音
  18. 脑肿瘤分割论文打卡2:E1D3 U-Net for Brain Tumor Segmentation
  19. Elasticsearch顶尖高手系列:高手进阶篇(二)
  20. php电子邮件群发源码,php电子邮件群发源码

热门文章

  1. STP——RSTP快生成树协议讲解
  2. c语言file函数头文件,文件操作函数 C语言 (FILE fputc fgetc fputs fgets fsca...
  3. 比害时新己50米地面蹦极交吻(组图)
  4. 长沙python哪个培训好
  5. Fiddler之日常使用简介
  6. Lisa Lambert:英特尔投资将加大AppUp和Tizen力度
  7. 计算机启动通常有热启动,计算机的启动通常有哪些三种方法?
  8. 苹果开发者证书,唯一标识和配置文件的作用及使用
  9. 2019年09月11日星期三 恒指/美原油/美黄金 走势分析
  10. js 简单实现 弹出确认 取消对话框