在 spring 数据 jpa 中使用 @PrimaryKeyJoinColumn 注释
Using @PrimaryKeyJoinColumn annotation in spring data jpa
我尝试使用 @PrimaryKeyJoinColumn
注释。执行此操作时,出现错误 - attempted to assign id from null one-to-one 属性.
用户已保存,但地址未保存。我想为 User
和 Address
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";
}
还有几个注意事项:
无论何时形成双向关联,应用程序开发人员都必须确保双方始终保持同步。
你不应该单独保存你的实体,你应该在你的关联上使用适当的 cascading。
您不应为 generated identifier 设置值。
当你在Address.user
上使用@MapsId
时,实际上意味着Address
实体将从一对一关联中借用标识符。所以,你不应该为 Address.id
使用 @GeneratedValue
注释。 (参见 this)
我尝试使用 @PrimaryKeyJoinColumn
注释。执行此操作时,出现错误 - attempted to assign id from null one-to-one 属性.
用户已保存,但地址未保存。我想为 User
和 Address
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";
}
还有几个注意事项:
无论何时形成双向关联,应用程序开发人员都必须确保双方始终保持同步。
你不应该单独保存你的实体,你应该在你的关联上使用适当的 cascading。
您不应为 generated identifier 设置值。
当你在
Address.user
上使用@MapsId
时,实际上意味着Address
实体将从一对一关联中借用标识符。所以,你不应该为Address.id
使用@GeneratedValue
注释。 (参见 this)