Spring Boot JPA一对一和共享主键需要手动分配

0pizxfdo  于 2022-11-05  发布在  Spring
关注(0)|答案(2)|浏览(150)

我使用Springboot和JPA来创建共享同一主键的两个表。
对于第一个表,我写着:

public class UserAccount implements Serializable
 {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   @OneToOne(mappedBy ="user", cascade = {CascadeType.REMOVE, CascadeType.MERGE, 
                                         CascadeType.REFRESH}, fetch=FetchType.LAZY)
   @PrimaryKeyJoinColumn
   private UserLogin login;
 }

对于第二个表,我写:

public class UserLogin implements Serializable
  {
    @Id
    private Long user_id;
    @OneToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}, 
               fetch=FetchType.LAZY)
   @MapsId("user_id")
   @JoinColumn(name = "user_id", referencedColumnName = "id")
   @Setter(AccessLevel.NONE)
   private UserAccount user;
   public void setUser(UserAccount user)
    {
     this.user = user;
     this.user_id = user.getId();    
    }
  }

为了简洁起见,省略了其他内容。

this.user_id = user.getId();

否则会出现错误:
休眠错误:必须在调用保存()之前手动分配此类的ID:
我想可以手动管理ID,但我无法获得正确的配置。

wribegjk

wribegjk1#

试试看:

public class UserLogin implements Serializable
  {
    @Id
    private Long user_id;

   @OneToOne(fetch=FetchType.LAZY)
   @MapsId
   @JoinColumn(name = "user_id")
   private UserAccount user;

   public UserAccount getUser() {
     return user;
   }
   public void setUser(UserAccount user) {
     this.user = user;
   }
  }

public class UserAccount implements Serializable
 {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
 }

若要保留UserLogin,请执行下列动作:

EntityManager em;
UserAccount user = em.find(UserAccount.class, 1L)
UserLogin login = new UserLogin();
login.setUser(user);
em.persist(login);
cgfeq70w

cgfeq70w2#

您有一个双向关系,但是用几个不能很好地配合使用的竞争选项Map它。(特别是使用PrimaryKeyJoinColumn)。如果您想要产生它,它不能也是引用中的外键值-并且您已经通过'mappedBy'设置将此关系设置为'other'端。它应该只是:

public class UserAccount implements Serializable {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   @OneToOne(mappedBy ="user", cascade = {CascadeType.REMOVE, CascadeType.MERGE, 
                                         CascadeType.REFRESH}, fetch=FetchType.LAZY)
   private UserLogin login;
 }

用户登录名应为:

public class UserLogin implements Serializable {
   @Id
   private Long user_id;
   @OneToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}, 
               fetch=FetchType.LAZY)
   @MapsId("user_id")
   @JoinColumn(name = "user_id", referencedColumnName = "id")
   @Setter(AccessLevel.NONE)
   private UserAccount user;
   public void setUser(UserAccount user) {
     this.user = user;   
   }
}

请注意,因为您在用户关系上有mapsId注解,所以一旦分配了ID,JPA将为您设置user_id属性-不需要手动设置它。您可以这样做,但是如果您这样做,您必须确保它之前已被分配-这需要在UserAccount上进行保存/刷新。如果您实际上没有使用Long user_id属性,您甚至不需要Map它;您可以只将用户属性标记为ID:

public class UserLogin implements Serializable {
   @Id
   @OneToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}, 
               fetch=FetchType.LAZY)
   @JoinColumn(name = "user_id", referencedColumnName = "id")
   @Setter(AccessLevel.NONE)
   private UserAccount user;
   public void setUser(UserAccount user) {
     this.user = user;   
   }
}

然后,可以使用UserAccount的长ID来查找UesrAccounts和UserLogin示例。

相关问题