一对一映射 Spring Data JPA

问题描述 投票:0回答:4

我有一个关于 Spring Boot 中一对一单向映射的问题。 我有一个 Customer 类,它与 Address 类有一对一的单向映射。

但是当我尝试将新客户与现有地址关联时,数据库会更新。 因此,两个客户现在与一个地址相关联。

据我了解,只有一位客户应该与一个唯一的地址相关联。我是否正确理解了这个概念,或者我在 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;
    :
}

数据.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);
}

数据库

spring-boot hibernate spring-data-jpa nhibernate-mapping
4个回答
0
投票

关于如何建立 @OneToOne 关系有 2 个选项:单向和双向:参见 hibernate 文档

向下滚动一点,您会发现以下内容:

当使用双向 @OneToOne 关联时,Hibernate 在获取子端时强制执行唯一约束。如果有多个子级与同一父级关联,Hibernate 将抛出 org.hibernate.exception.ConstraintViolationException

这意味着只有在获取和具有双向关联时才会出现异常。因为 Hibernate 会进行额外的查询来查找依赖实体,会找到其中 2 个,这不符合 @OneToOne 关系,并且必须抛出异常。

“修复”实体唯一性的一种方法是使

cAddr
唯一:

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="aid", unique=true)
private Address cAddr;

如果您创建数据库表,通过设置 hbm2ddl 属性,这将为

aid
列添加唯一约束。

我真的建议阅读以下内容:

  1. @OneToOne javadoc本身提供了如何正确执行所有操作的示例(对于您来说示例1和2是最有用的)
  2. 查看 Vlad 的关于 @OneToOne 的博客。它一定是你能找到的最好的。至少跳到“最有效的映射”一章并使用
    @MapsId
    实现双向并共享PK。

也许你会想到使用@ManyToOne选项(至少我可以想象客户可以有多个地址)


0
投票

这不是

One-to-Many
关系。它是
One-to-Many
,因为一个对象有多个相关对象。 查看这篇文章

示例:

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()
}

0
投票

在此站点查看 Spring Boot 中使用外键列的单向一对一映射的实现逐步 Restful Web 服务示例。


-1
投票

在这个站点查看步骤“3.单向一对一映射演示”,基本上是您想要做的事情的抄袭。

© www.soinside.com 2019 - 2024. All rights reserved.