当前位置:网站首页>【精品】利用动态代理实现事务统一管理 二
【精品】利用动态代理实现事务统一管理 二
2022-04-23 08:11:00 【梁云亮】
DAO层
- 接口
public interface DeptDao{
int insert(Dept dept);
}
public interface EmpDao{
int insert(Emp emp);
}
- 实现类
public class DeptDaoImpl implements DeptDao{
@Override
public int insert(Dept dept){
QueryRunner queryRunner = new QueryRunner(TransactionManager.getDataSource());
// ....... 具体操作数据库实现插入数据到数据库表的操作
}
}
public class EmpDaoImpl implements EmpDao{
@Override
public int insert(Emp emp){
QueryRunner queryRunner = new QueryRunner(TransactionManager.getDataSource());
// ....... 具体操作数据库实现插入数据到数据库表的操作
}
}
Service层
- 接口
public interface EmpService{
/** * 同时添加员工,以及该员工所在的部门 */
int insert(Emp emp,Dept dept);
}
- 实现类
public class EmpServiceImpl{
private DeptDao dpetDao = new DeptDaoImpl();
private EmpDao empDao = new EmpDaoImpl();
/** * 同时添加员工,以及该员工所在的部门 */
int insert(Emp emp,Dept dept){
deptDao.insert(conn,dept);
System.out.println(3/0);
empDao.insert(conn,emp);
}
}
事务管理器
public class TransactionManager {
private static DataSource dataSource;
//用来给本地线程放置Connection代理对象
private static ThreadLocal<Connection> proxyConnLocal = new ThreadLocal<>();
//用来给本地线程放置真正的Connection对象
private static ThreadLocal<Connection> realConnLocal = new ThreadLocal<>();
static {
Properties properties = new Properties();
String propertiesFile = "/mysql.properties";
try {
InputStream is = TransactionManager.class.getResourceAsStream(propertiesFile);
properties.load(is);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private TransactionManager() {
}
/** * 获取数据源DataSource * * @return 如果需要开启事务的话,返回datasource的代理,否则返回原生的datasource */
public static DataSource getDataSource() {
DataSource ds = (DataSource) Proxy.newProxyInstance(dataSource.getClass().getClassLoader(), dataSource.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getConnection".equals(method.getName())) {
return proxyConnLocal.get();
} else {
return method.invoke(proxy, args);
}
}
});
return ds;
}
/** * 开启事务 * * @throws SQLException */
public static void startTransaction() throws SQLException {
Connection conn = dataSource.getConnection();
//设置事务不自动提交
conn.setAutoCommit(false);
//将真正的Connection对象放到本地线程中
realConnLocal.set(conn);
//开启事务
isTransactionEnabled.set(true);
//设置Connection对象不自动关闭
Connection proxyConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("close".equals(method.getName())) {
//
return null;
} else {
return method.invoke(conn, args);
}
}
});
//将Connection代理对象放到本地线程中
proxyConnLocal.set(proxyConn);
}
/** * 提交事务 */
public static void commitTransaction() {
DbUtils.commitAndCloseQuietly(proxyConnLocal.get());
}
/** * 回滚事务 */
public static void rollbackTransaction() {
DbUtils.rollbackAndCloseQuietly(proxyConnLocal.get());
}
public static void release() {
DbUtils.closeQuietly(realConnLocal.get());
realConnLocal.remove();
proxyConnLocal.remove();
isTransactionEnabled.remove();
}
}
动态代理事务增强
public class ServiceProxy implements InvocationHandler {
private Object service;
public ServiceProxy(Object service) {
this.service = service;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res = null;
//方法上面是否标有事务
try {
TransactionManager.startTransaction();
//业务方法
res = method.invoke(service, args);
TransactionManager.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
TransactionManager.rollbackTransaction();
} finally {
TransactionManager.release();
}
return res;
}
public Object getProxy() {
return Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), this);
}
}
测试代码
public static void main(String[] args) throws SQLException {
Dept dept = new Dept(20,"ACCOUNTING","NEWYORK");
Emp emp = new Emp(7369, "SMITH", "CLERK", 7902,LocalDate.of(1980, 12, 17), 800D, null, 20);
EmpService empService = EmpServiceImpl();
ServiceProxy serviceProxy = new ServiceProxy(empService);
EmpService proxy = (EmpService) serviceProxy .getProxy();
boolean addRes = proxy.add(emp,dept);
System.out.println(addRes);
}
存在问题
采用本博客介绍的技术基本上就解决了事务的统一管理。但上面代码还存在一个小问题,就是这样一来所有执行DeptDao的insert()和EmpDao的insert()方法都会有事务支持,具体解决方案就是在True中添加一个本地变量来标识是否需要返回支持事务的DataSource就可以了。有关这一块的讲解,请参看代码:https://gitee.com/hcshow/credits,项目中有详细的代码讲解与应用案例。
版权声明
本文为[梁云亮]所创,转载请带上原文链接,感谢
https://hcshow.blog.csdn.net/article/details/124336988
边栏推荐
- freertos学习02-队列 stream buffer message buffer
- QT compilation qtxlsx Library
- PgSQL wants to implement all kinds of column sub query operations of MySQL
- Campus transfer second-hand market source code download
- 线程的调度(优先级)
- Failed to convert a NumPy array to a Tensor(Unsupported Object type int)
- vmware 搭建ES8的常见错误
- How to encrypt devices under the interconnection of all things
- lgb,xgb,cat k折交叉验证
- RPC procedure
猜你喜欢
Green apple film and television system source code film and television aggregation film and television navigation film and television on demand website source code
《深度学习》学习笔记(八)
JVM工具之Arthas使用
vslam PPT
引用传递1
正点原子携手OneOS直播 OneOS系统教程全面上线
【路科V0】验证环境2——验证环境组件
QT compilation qtxlsx Library
测试你的机器学习流水线
AQS & ReentrantLock 实现原理
随机推荐
Navicat remote connection MySQL
面了一圈,整理了这套面试题。。
分布式消息中间件框架选型-数字化架构设计(7)
Misunderstanding of flush () method of OutputStream class
Asan minimalism
Search the complete navigation program source code
Queue (C language / linked list)
程序,进程,线程;内存结构图;线程的创建和启动;Thread的常用方法
Using qlst excel file
The annotation is self-defined by implementing the parameter parser handlermethodargumentresolver interface
正点原子携手OneOS直播 OneOS系统教程全面上线
idea配置连接远程数据库MySQL,或者是Navicat连接远程数据库失败问题(已解决)
Community group purchase applet source code + interface DIY + nearby leader + supplier + group collage + recipe + second kill + pre-sale + distribution + live broadcast
项目上传部分
二维01背包
One click cleanup of pycharm and jupyter cache files under the project
Comparison of indoor positioning technology
关于ORB——SLAM运行中关键帧位置越来越近的异常说明
Shell script advanced
Record: JS several methods to delete one or more items in the array