一对一映射 Spring 数据 JPA
One To One Mapping Spring Data JPA
我对 Spring Boot 中的一对一单向映射有疑问。
我有一个客户 class 与地址 class.
的一对一单向映射
但是当我尝试将新客户与现有地址相关联时,数据库会更新。
因此两个客户现在与一个地址相关联。
据我了解,只有一位客户应与一个唯一地址相关联。我是否正确理解了这个概念,还是我在 Spring Boot/ Spring Data JPA/ Hibernate 中做错了什么?
客户
@Entity
public class Customer {
@Id
private Long cId;
private String cName;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="aid")
private Address cAddr;
:
}
地址
@Entity
public class Address {
@Id
private Long aid;
private String town;
private String county;
:
}
data.sql
insert into address values (100, "New York", "NY");
insert into customer values (1, "John Smith", 100);
Application.java
@Override
public void run(String... args) throws Exception {
Customer c1 = new Customer((long)5, "Mr. Men");
Optional<Address> a100 = ar.findById((long)100);
c1.setcAddr(a100.get());
cr.save(c1);
}
数据库
查看此 site 中的步骤“3. 单向一对一映射演示”,基本上是您正在尝试执行的操作的副本。
这不是One-to-Many
关系。它是 One-to-Many
,因为 一个 对象具有 多个 相关对象。 Checkout this article.
示例:
Post.java
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class Post {
@Id
@GeneratedValue
@Column(name = "post_id")
private Long id;
@Column
private String postHeader;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
public void addComment(Comment comment) {
comments.add(comment);
}
public void removeComment(Comment comment) {
comments.remove(comment);
}
// equals() and hashCode()
}
评论:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class Comment {
@Id
@GeneratedValue
@Column(name = "postcom_id")
private Long id;
@Column
private String text;
// equals() and hashCode()
}
关于如何建立@OneToOne 关系有两种选择:单向和双向:see hibernate doc。
当您向下滚动一点时,您会发现以下内容:
When using a bidirectional @OneToOne association, Hibernate enforces the unique constraint upon fetching the child-side. If there are more than one children associated with the same parent, Hibernate will throw a org.hibernate.exception.ConstraintViolationException
这意味着只有在获取和具有双向关联时才会出现异常。因为 Hibernate 将进行额外的查询来查找依赖实体,将找到其中的 2 个,它们不符合 @OneToOne 关系,并且必须抛出异常。
“修复”实体唯一性的一种方法是使 cAddr
唯一:
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="aid", unique=true)
private Address cAddr;
如果您创建数据库表,通过 setting hbm2ddl property 这将向 aid
列添加唯一约束。
我强烈推荐阅读以下内容:
- @OneToOne javadoc 本身提供了如何正确执行所有操作的示例(对您而言,示例 1 和 2 最有用)
- 勾选Vlad's blog about @OneToOne。它一定是您能找到的最好的。至少跳转到“最有效的映射”一章并使用
@MapsId
. 实现双向和共享PK
也许你会想到使用@ManyToOne 选项(至少我可以想象客户可以有多个地址)
我对 Spring Boot 中的一对一单向映射有疑问。 我有一个客户 class 与地址 class.
的一对一单向映射但是当我尝试将新客户与现有地址相关联时,数据库会更新。 因此两个客户现在与一个地址相关联。
据我了解,只有一位客户应与一个唯一地址相关联。我是否正确理解了这个概念,还是我在 Spring Boot/ Spring Data JPA/ Hibernate 中做错了什么?
客户
@Entity
public class Customer {
@Id
private Long cId;
private String cName;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="aid")
private Address cAddr;
:
}
地址
@Entity
public class Address {
@Id
private Long aid;
private String town;
private String county;
:
}
data.sql
insert into address values (100, "New York", "NY");
insert into customer values (1, "John Smith", 100);
Application.java
@Override
public void run(String... args) throws Exception {
Customer c1 = new Customer((long)5, "Mr. Men");
Optional<Address> a100 = ar.findById((long)100);
c1.setcAddr(a100.get());
cr.save(c1);
}
数据库
查看此 site 中的步骤“3. 单向一对一映射演示”,基本上是您正在尝试执行的操作的副本。
这不是One-to-Many
关系。它是 One-to-Many
,因为 一个 对象具有 多个 相关对象。 Checkout this article.
示例:
Post.java
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class Post {
@Id
@GeneratedValue
@Column(name = "post_id")
private Long id;
@Column
private String postHeader;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
public void addComment(Comment comment) {
comments.add(comment);
}
public void removeComment(Comment comment) {
comments.remove(comment);
}
// equals() and hashCode()
}
评论:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class Comment {
@Id
@GeneratedValue
@Column(name = "postcom_id")
private Long id;
@Column
private String text;
// equals() and hashCode()
}
关于如何建立@OneToOne 关系有两种选择:单向和双向:see hibernate doc。
当您向下滚动一点时,您会发现以下内容:
When using a bidirectional @OneToOne association, Hibernate enforces the unique constraint upon fetching the child-side. If there are more than one children associated with the same parent, Hibernate will throw a org.hibernate.exception.ConstraintViolationException
这意味着只有在获取和具有双向关联时才会出现异常。因为 Hibernate 将进行额外的查询来查找依赖实体,将找到其中的 2 个,它们不符合 @OneToOne 关系,并且必须抛出异常。
“修复”实体唯一性的一种方法是使 cAddr
唯一:
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="aid", unique=true)
private Address cAddr;
如果您创建数据库表,通过 setting hbm2ddl property 这将向 aid
列添加唯一约束。
我强烈推荐阅读以下内容:
- @OneToOne javadoc 本身提供了如何正确执行所有操作的示例(对您而言,示例 1 和 2 最有用)
- 勾选Vlad's blog about @OneToOne。它一定是您能找到的最好的。至少跳转到“最有效的映射”一章并使用
@MapsId
. 实现双向和共享PK
也许你会想到使用@ManyToOne 选项(至少我可以想象客户可以有多个地址)