栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

在mybatis拦截器实现双写并且支持处理事务的方法(使用TransactionalEventListener实现)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在mybatis拦截器实现双写并且支持处理事务的方法(使用TransactionalEventListener实现)

书接上文:不使用binlog,canal,kafka等,只用java+mybatis拦截器来实现项目中的异步双写主从数据库,代码逻辑全整理
我目前在双写的项目发现中还差一个缺陷,就是如果有事务注解的情况下,发生了回滚,我的异步双写成功写入,但是主库插入失败,这里就用到了TransactionalEventListener作为参考来实现异步双写的事务回滚
参考如下:TransactionalEventListener使用场景以及实现原理,最后要躲个大坑

然后再我的拦截器中应用,新加package如下


TrxEvent继承ApplicationEvent类,作为传参我自定义了几个字段

public class TrxEvent extends ApplicationEvent {
    private String tableName;
    private Object obj;

    private Map param;
    private String sqlCommandType;

    private String isObjOrMap;

    public TrxEvent(Object source) {
        super(source);
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

    public Map getParam() {
        return param;
    }

    public void setParam(Map param) {
        this.param = param;
    }

    public String getSqlCommandType() {
        return sqlCommandType;
    }

    public void setSqlCommandType(String sqlCommandType) {
        this.sqlCommandType = sqlCommandType;
    }

    public String getIsObjOrMap() {
        return isObjOrMap;
    }

    public void setIsObjOrMap(String isObjOrMap) {
        this.isObjOrMap = isObjOrMap;
    }
}

其中构造需要实现如下

  public TrxEvent(Object source) {
        super(source);
    }

然后是监听器UserCreatedEventListener,注入我的双写service和ApplicationEventPublisher做发布事件操作

@Component
public class UserCreatedEventListener {

    @Autowired
    private DoubleWriteService doubleWriteService;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public UserCreatedEventListener(DoubleWriteService doubleWriteService) {
        this.doubleWriteService = doubleWriteService;
    }

    @TransactionalEventListener(fallbackExecution = true, phase = TransactionPhase.AFTER_COMMIT)
    public void processUserCreatedEvent(TrxEvent event) {
        if (event.getIsObjOrMap().equals("obj")){
            if (DoubleWriteConstants.UPDATE.equals(event.getSqlCommandType())){
                doubleWriteService.update(event.getTableName(),event.getObj());
            }else if (DoubleWriteConstants.INSERT.equals(event.getSqlCommandType())){
                doubleWriteService.insert(event.getTableName(), event.getObj());
            }
        }else if (event.getIsObjOrMap().equals("map")){
            if (DoubleWriteConstants.UPDATE.equals(event.getSqlCommandType())){
                doubleWriteService.update(event.getTableName(),event.getParam());
            }else if (DoubleWriteConstants.INSERT.equals(event.getSqlCommandType())){
                doubleWriteService.insert(event.getTableName(), event.getParam());
            }
        }


    }


    public void publish(String isObjOrMap, String sqlCommandType, Map param,Object obj,String tableName){
        TrxEvent event = new TrxEvent(this);
        event.setIsObjOrMap(isObjOrMap);
        event.setTableName(tableName);
        event.setObj(obj);
        event.setParam(param);
        event.setSqlCommandType(sqlCommandType);
        applicationEventPublisher.publishEvent(event);
    }
}

关键注解如下,一定要设置事务阶段是AFTER_COMMIT提交后才执行

最后去mybatis拦截器里,调用发布事件

最后调试截图就不贴了,基本都能保证事务成功提交后,从库开始写入。否则失败回滚后,直接从库不执行写入操作

暑期编程PK赛 得CSDN机械键盘等精美礼品!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1016240.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号