6

mybatis-plus 批量插入时事务失效

 2 years ago
source link: https://www.oschina.net/question/5451389_2324209
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

mybatis-plus 批量插入时事务失效

osc_87307087 发布于 10/26 16:27
阅读 559

各位大佬,小弟最近开发的时候碰到一个很诡异的问题,如下:

首先是一个接口,这个接口里面有两个方法,分别是方法A和方法B,在方法A中使用mybatis-plus提供的批量插入API,saveOrUpdateBatch,成功批量插入了C表数据,然后在方法B中查询方法A批量插入的C表数据,发现查不到,然后拿日志打印的查询语句去数据库执行,是可以查到数据的。

之后,我尝试着在方法A中把批量插入改成for循环一个一个插入,然后方法B不变,这回就可以查询到A方法中插入的C表数据了。

事后,小弟排除了很多可能,包括方法B的查询条件是否错误,方法A批量插入的数据是否有误,包括事务配置,这些均没有发现有不对的地方,不知道是我哪里配置不对,还是mybatis-plus本身的问题。

魔力猫
10/27 09:14

继续检查事务配置,包括你程序事务设定和数据库隔离等级,这个问题大概率是A和B不在一个事务。A执行后还没有提交事务,B就执行了,所以B查不到A的。

你一个个插入,那可能就是插1个提交了一次事务,于是B就拿到了。

sprouting
10/27 09:31

不确定你的具体配置,但可能有这么几个问题

1,做了主从分离,查询的时候从库还没有同步,等你复制好语句的时候从库已经同步了

2、事务,你的A方法和B方法不再同一个事务之中导致的。也可能你的A方法和B方法采用的事务策略是新建事务,导致查不到

魔力猫
10/27 09:53
我认为主从分离的可能性不大,因为问题的标签上是Oracle而不是MySQL。Oracle有钱做主从分离,那干嘛不干脆再稍微加一点,直接RAC?!
_Mr_Right_
10/27 10:02

mybatis-plus本身的问题概率不大,因为你的描述是常见需求,要出问题早出问题了。

其次,你可以吧你的代码脱敏,贴出来,大家一起集思广益。

osc_87307087
10/27 14:45
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="search*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="del*" rollback-for="java.lang.Exception"/>
        <tx:method name="delete*" rollback-for="java.lang.Exception"/>
        <tx:method name="insert*" rollback-for="java.lang.Exception"/>
        <tx:method name="update*" rollback-for="java.lang.Exception"/>
        <tx:method name="save*" rollback-for="java.lang.Exception"/>
        <tx:method name="*" rollback-for="java.lang.Exception"/>
    </tx:attributes>
</tx:advice>

这个是事务的部分配置,有尝试在在name="*"的那一行加上

propagation="SUPPORTS"

也是不生效。

以下是相关的代码:

最外层的接口:

// 拷贝申请材料数据
wxHandinMatService.copyTrMatBasToWechat(applyId, busType, applyInfo.getSenderOrigin(), applyUserId);
// 根据业务内容重置必上传属性
wxHandinMatService.resetHandinMatIsEss(applyId, busType);

A方法:

@Override
    public void copyTrMatBasToWechat(String applyId, String busType, String senderOrigin, String applyUserId) {
        List<WxHandinMat> handinMats = listHandinMat(applyId, busType, false);
        // 如果为空,则拷贝
        if (CollectionUtils.isEmpty(handinMats)) {
            // TODO
            List<TrMatBas> trMatBasList = trMatBasService.listByBusType(busType, senderOrigin);
            if (!CollectionUtils.isEmpty(trMatBasList)) {
                List<WxHandinMat> list = new ArrayList<>();
                for (TrMatBas matBas : trMatBasList) {
                    WxHandinMat handinMat = new WxHandinMat();
                    // TODO
list.add(handinMat);
                }
                // 这里批量插入之后,B方法查询不到
                if (!CollectionUtils.isEmpty(list)) {
//                    for (WxHandinMat handinMat : list) {
//                        saveOrUpdate(handinMat); // 单独一个一个插入,B方法可以查询到
//                    }
                    saveOrUpdateBatch(list);
                }
            }
        }
    }
@Override
public void resetHandinMatIsEss(String applyId, String busType) {
    List<WxHandinMat> wxHandinMats = listHandinMat(applyId, busType, false);
    if (!CollectionUtils.isEmpty(wxHandinMats)) {
        // TODO
}
}
osc_87307087
10/27 14:48
A方法和B方法都是同一个service的不同接口 A方法中的List<WxHandinMat> handinMats = listHandinMat(applyId, busType, false);和B方法中的List<WxHandinMat> wxHandinMats = listHandinMat(applyId, busType, false);是同一个接口
飞奔地蜗牛
10/27 15:38

问题多半在这个listHandinMat方法里面。仔细检查代码把,多半是一些低级的问题导致的。

osc_87307087
今天 09:57
listHandinMat只是一个简单的QueryWrapper条件查询,倒没看到有什么问题
我家有猪
10/27 18:35
saveOrUpdateBatch的时候指定batchSize
ducat7
今天 10:17

1、saveOrUpdateBatch(…)方法也是循环生成insert语句,你可以优化成一条insert语句(这是MyBatis优势之一)。

2、先插后查不到,不在一个session里、DB就没及时处理等有关。

3、MyBatis里的方法都是一个方法一个事务,所以,不在一个session管道里。(JPA不注解也是如此)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK