简体   繁体   English

Spring 当外部事务提交时启动,它执行与之前由内部 (REQUIRED_NEW) 事务完成的相同的插入

[英]Spring Boot when outer transaction commits it performs same inserts as was previously done by inner (REQUIRED_NEW) transaction

@Entity
public class User {

  @Id
  private Long id;

  @OneToOne(mappedBy = "user", cascade = {CascadeType.MERGE,CascadeType.PERSIST}, fetch = FetchType.LAZY)
  private Profile profile;
}

@Entity
public class Profile {

  @Id
  @Column(name = "user_id")
  private Long id;

  @OneToOne
  @MapsId
  @JoinColumn(name = "user_id")
  private User user;
}

public class ProcessUsers {
  @Transactional
  public void processUsers() {
       List<Users> users = repo.getUsers();

       processPart.processPart(users.getPart())
  }
}

public class ProcessPart {

   @Transactional(propagation = Propagation.REQUIRES_NEW)
   public void processPart(List<User> users) { 
      users.forEach(user -> user.setProfile(new Profile(user))
      repo.saveAll(users)
   }  
}

I have outer transaction which loads Users from database.我有从数据库加载用户的外部事务。 Then that users are splitted to parts and they go to processing in new (Requires_new) inner transaction.然后用户被分成几部分,他们 go 在新的(Requires_new)内部交易中处理。 During this inner transaction for every user i create profile entity then save these users.在此内部事务中,我为每个用户创建配置文件实体,然后保存这些用户。 When inner transaction ends it performs commit and sql inserts for new profiles and updates for already existing users.当内部事务结束时,它会为新的配置文件执行提交和 sql 插入,并为现有用户执行更新。 But when outer transaction ends and performs commit it does the same inserts and updates and i get unique primary key violation.但是,当外部事务结束并执行提交时,它会执行相同的插入和更新,并且我会遇到唯一的主键冲突。

logs:日志:

JpaTransactionManager  : Initiating transaction commit
JpaTransactionManager  : Committing JPA transaction on EntityManager [SessionImpl(48420828<open>)]
org.hibernate.SQL         : insert into profile (user_id, another_field) values (?, ?)
org.hibernate.SQL         : update user set updated_field = ? where id=?
JpaTransactionManager     : Closing JPA EntityManager [SessionImpl(48420828<open>)] after transaction


JpaTransactionManager        : Resuming suspended transaction after completion of inner transaction
JpaTransactionManager        : Initiating transaction commit
JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(713565825<open>)]
org.hibernate.SQL            : insert into profile (user_id, another_field) values (?, ?)
SqlExceptionHelper   : SQL Error: 23505, SQLState: 23505
SqlExceptionHelper   : Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.PROFILE(USER_ID) 

I guess this is because of sessions are different (SessionImpl(48420828), SessionImpl(713565825)).我猜这是因为会话不同(SessionImpl(48420828)、SessionImpl(713565825))。

How can i prevent outer transaction from repeating sql queries?如何防止外部事务重复 sql 查询?

If I am not mistaken given that this is a bi-directional relationship you need to also set the user to the Profile :如果我没有记错的话,鉴于这是双向关系,您还需要将用户设置为Profile

for (User user: users) {
   Profile profile = new Profile()
   profile.setUser(user)
   user.setProfile(profile)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM