在 spring 数据 jpa 中使用 @PrimaryKeyJoinColumn 注释

Using @PrimaryKeyJoinColumn annotation in spring data jpa

我尝试使用 @PrimaryKeyJoinColumn 注释。执行此操作时,出现错误 - attempted to assign id from null one-to-one 属性.

用户已保存,但地址未保存。我想为 UserAddress table 创建一个公共主键。我找到了一个例子 here.

请告诉我我做错了什么,为什么这个例子对我不起作用?

https://github.com/mytestPercon/TestHiber

User.java

@Entity
@Table(name = "user", schema = "TestKeyJoin")
public class User implements Serializable {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private Long id;

   @Basic
   @Column(name = "name")
   private String name;

   @OneToOne(mappedBy = "user")
   @PrimaryKeyJoinColumn
   private Address activated;

   // Getter and Setter ...
}

Address.java

@Entity
@Table(name = "Address", schema = "TestKeyJoin")
public class Address implements Serializable {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private long id;

   @Basic
   @Column(name = "city")
   private String city;

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

   // Getter and Setter ...

}

SaveController.java

@Controller
public class SaveController {

   @Autowired
   ServiceJpa serviceJpa;

   @GetMapping(value = "/saveUser")
   public String getJpa () {
      User user = new User();
      user.setId(1L);
      user.setName("Michael Joseph Jackson");
      serviceJpa.saveUser(user);

      Address address = new Address();
      address.setId(1L);
      address.setCity("Los Angeles");
      serviceJpa.saveActivated(address);

      return "/saveUser";
   }
}

删除地址实体中 id 字段的 @GeneratedValue(strategy = GenerationType.IDENTITY),因为它是用户实体的外键,不应自动递增。 EDIT:Try 通过添加这些行

 public String getJpa () {

            User user = new User();
            user.setId(1L);
            user.setName("Michael Joseph Jackson");
            Address address = new Address();
            address.setId(1L);
            address.setCity("Los Angeles");
            user.setActivated(address);
            serviceJpa.saveUser(user);
             return "/saveUser";
        }

尝试按以下方式更正您的映射:

@Entity
@Table(name = "user", schema = "TestKeyJoin")
public class User implements Serializable {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private Long id;

   @Column(name = "name")
   private String name;

   @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
   private Address address;

   // ...
}

@Entity
@Table(name = "Address", schema = "TestKeyJoin")
public class Address implements Serializable {

   @Id
   private Long id;

   @Column(name = "city")
   private String city;

   /* You can use @PrimaryKeyJoinColumn instead of the @MapsId here.
      See the Example 153. Derived identifier @PrimaryKeyJoinColumn
      from the hibernate documentation.
   */
   @OneToOne
   @MapsId
   @JoinColumn(name = "id")
   private User user;

   // ...
}

然后通过以下方式保存用户:

@GetMapping(value = "/saveUser")
public String getJpa () {

   User user = new User();
   user.setName("Michael Joseph Jackson");

   Address address = new Address();
   address.setCity("Los Angeles");

   // make both sides of the bidirectional @OneToOne in-sync
   user.setAddress(address);
   address.setUser(user);

   serviceJpa.saveUser(user);

   return "/saveUser";
}

还有几个注意事项:

  1. 无论何时形成双向关联,应用程序开发人员都必须确保双方始终保持同步。

  2. 你不应该单独保存你的实体,你应该在你的关联上使用适当的 cascading

  3. 您不应为 generated identifier 设置值。

  4. 当你在Address.user上使用@MapsId时,实际上意味着Address实体将从一对一关联中借用标识符。所以,你不应该为 Address.id 使用 @GeneratedValue 注释。 (参见 this