由于给的信息不多,不过依照hibernate
的事务处理性质,我给予以下几个点来梳理哈问题,题主可以根据这些点去check
一下
* 首先这个报错Duplicate entry '1588162468514' for key 'PRIMARY'
是数据库报出来的
你去给数据库执行sql
插入操作,但是已有主键存在,所以sql
报错
* 那为啥明明是查询操作,却执行了插入操作呢?
从堆栈上也可以看到,开始确实是list()
操作,但是关键就是出在了这个list()
操作之前,需要进行一次flush
* hibernate
的flush
会把当前Session
开启的事务中所有登记的操作全部发给数据库执行一遍(但不提交事务,这是与commit
的区别),并且按照insert,update...
等顺序去执行
所以此时我猜想,你的方法ProjAssociationServiceImpl.asyncBusiOppoForAsso
应该是有个事务@Transactional
的(就算没有,asyncBusiOppoForAsso
再外层的方法估计有,总之肯定被包到一个事务里了)
* 因为有了事务,恰好你的查询方法ProjAssociation findByBusiCode(String busiCode)
使用了NativeQueryImpl
,而NativeQueryImpl
执行beforeQuery
时要先判断一下是否需要flush
,也就是方法NativeQueryImpl.shouldFlush
* 因此执行flush
的话,ProjAssociationServiceImpl.asyncBusiOppoForAsso
中所有在findByBusiCode
之前登记的insert
都要执行了。那这里面有2条以上sql主键重复问题,当然就会报错,虽然不是你查询的问题,但是恰好这个查询相当于提前执行了一次flush
结合以上的点,那要检查的东西就很简单了,去找找在asyncBusiOppoForAsso
内(或外层事务包裹范围内),findByBusiCode
之前做过的save()
操作,并且着重检查save()
时的实体的主键生成策略。
因为没有其他信息,我下面只是举个例子
User user1 = new User();
user1.setName("测试1");
userRepository.save(user1);
User user2 = new User();
user2.setName("测试2");
userRepository.save(user2);
Student student = repository.findByName(name);
虽然最后只是执行一个查询,但是前面有两个User
的save
操作,如果User
的主键生成策略导致最终user1
,user2
主键都是相同的,那repository.findByName
执行时会触发一次flush
,那此时之前登记的user1
,user2
的insert
操作就会一起执行一遍,导致最终报错
以上就是我的看法吧,不过没有复现你的问题,只能说提供一些参考意见,希望有所帮助~那。。。拜了个拜~(* ̄rǒ ̄)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…