首页 > 解决方案 > Hibernate PostgreSQL OneToOne 关系首先触发子查询

问题描述

我正在构建应用程序来在 PostgreSQL 上学习 Hibernate。我目前正在尝试将变量添加到具有 OneToOne 关系的数据库中。

首先,我在我的数据库中创建了两个表,其架构如下。在person_detail表上,它的主键也是person表的外键。

数据库模式

然后我创建了两个类,PersonPersonDetail. PersonDetailPerson具有 OneToOne 关系的孩子。我使用下面的代码添加personaspersonDetail属性。

Person person = new Person(
        "Rick",
        1.7,
        dateFromString("1969-4-2"),
        new Date()
);
PersonDetail personDetail =
        new PersonDetail("myemail@email.com", "Marley");
person.setPersonDetail(personDetail);

session.beginTransaction();

session.save(person);
session.save(personDetail);

session.getTransaction().commit();

System.out.println(person.toString());

但是上面代码的问题是Hibernate首先执行子查询而不是父查询。

Hibernate:插入person_detail(地址,电子邮件)值(?,?)

而且由于person仍然是空的,我们不能插入任何行,person_detail因为它违反了外键约束。

有没有办法解决这个问题?谢谢!

如果有人想检查我如何注释这两个类,我将代码放在下面。

@Entity
@Table(name="person")
@Data
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

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

    @Column(name="height")
    private double height;

    @Column(name="birth_date")
    private Date dateBirth;

    @Column(name="last_seen")
    private Date lastSeen;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "id")
    private PersonDetail personDetail;

    public Person() {}

    public Person(String name, double height, Date dateBirth, Date lastSeen){
        this.name = name;
        this.height = height;
        this.dateBirth = dateBirth;
        this.lastSeen = lastSeen;
    }
}


@Data
@Entity
@Table(name="person_detail")
public class PersonDetail {
    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

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

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

    public PersonDetail(){}

    public PersonDetail(String email, String address){
        this.email = email;
        this.address = address;
    }
}

标签: javapostgresqlhibernate

解决方案


我看到你在表中有主键作为表person_details的外键person,你可以@PrimaryKeyJoinColumn这样使用:

@Entity
@Table(name="person")
@Data
public class Person {

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

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

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

    @OneToOne(mappedBy = "person", cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private PersonDetail personDetail;

    public Person() {}

    public Person(String name, String height) {
        this.name = name;
        this.height = height;
    }
}

@Data
@Entity
@Table(name="person_detail")
public class PersonDetail {

    @Id
    @Column(name="id")
    private Long id;

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

    @OneToOne
    @MapsId
    @JoinColumn(name = "id", referencedColumnName = "id")
    private Person person;


    public PersonDetail(){}

    public PersonDetail(String email){
        this.email = email;
    }
}

如果您保存实体,请不要忘记将 Person 设置为 PersonDetails:

Person person = new Person("Rick", "1.7");
        
PersonDetail personDetail = new PersonDetail("myemail@email.com");
personDetail.setPerson(person);

person.setPersonDetail(personDetail);
        
repository.save(person);

推荐阅读