一 问题复现
orcal 可以通过
select equence.nextval from dual
获取序列,作为新增表数据的主键。
当我们批量新增的时候,我们可以使用 for循环来组装Bean集合,然后批量新增。但是我们用多线程在同一个事务内开多线程访问序列值时,会取出同一个值。本次使用的是 lambda的foreach。在循环中居然发现获取的多个序列值一样。
二 问题原因
在同一个事务内开多线程访问序列值时,会取出同一个值。
三 解决办法
1、将多线程异步循环,改为单线程循环,如 lambda的foreach 改为 普通for循环。
2、将查询语句放在一个新事务中,同时增加同步约束。
@Transactional(value = 'mytran', propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class })@Overridepublic synchronized Long getNextVal() {return mapper.getNextVal();}
注意:
另如果在本类中调用时直接调用时事务不会生效,需要通过接口变更去调用。因为 在一个Service内部,事务方法之间的嵌套调用,普通方法和事务方法之间的嵌套调用,都不会开启新的事务.是因为spring采用动态代理机制来实现事务控制,而动态代理最终都是要调用原始对象的,而原始对象在去调用方法时,是不会再触发代理了!
只有代理对象proxy直接调用的那个方法才是真正的走代理的。

文章转载自全栈的程序员,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




