gpt4 book ai didi

java - @PrimaryKeyJoinColumn 未选择共享 key

转载 作者:行者123 更新时间:2023-11-30 05:53:23 25 4
gpt4 key购买 nike

我之前让 @PrimaryKeyJoinColumn 工作,现在我正在尝试使用 spring boot,但我不知道我错过了什么,这很奇怪,因为似乎我已经做对了一切:

人员类别:

    @Table(name = "PERSON")
@Entity

@Getter
@Setter
public class Person {

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


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

@OneToOne(cascade = CascadeType.PERSIST)
@PrimaryKeyJoinColumn
private Department department;
}

院系类别:

    @Table(name = "DEPARTMENT")
@Entity
@Getter
@Setter
public class Department {

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

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


@OneToOne(mappedBy = "department")
private Person person;
}

服务类别:

   @Transactional
public void addPerson() {
Person person = new Person();
person.setName("person 1");
Department department = new Department();
department.setName("test");
department.setPerson(person);
person.setDepartment(department);
personRepository.save(person);
}

这就是我在数据库中得到的:人员表:

ID   Name
13 person 1

部门表:

ID  Name
18 test

所需的输出:两个 ID 应该相同(人员 ID 应该是 18 而不是 13)有什么想法吗?

<小时/>

更新:hibernate 总是尝试插入没有 ID 的 Person ,因此如果我从 Person ID 中删除自动增量并尝试插入具有现有部门的人员,我会得到:

Hibernate: insert into person (name) values (?)

Field 'id' doesn't have a default value
<小时/>

更新 2:看来 @PrimaryKeyJoinColumn 不会像部门类一样处理 ID 生成,所以我需要使用生成器。我想知道,因为相同的注释适用于继承连接,而无需对子类的 ID 执行任何操作。所以我期待一个答案来解释为什么 ID 生成在 Inheritance join 中工作,而 OneToOne 需要一个生成器

最佳答案

尽管为一个人创建整个部门至少是不好的命名(部门通常由许多人组成),但我假设您确实正在寻找具有共享主键的一对一关系。

最好的解决方案(最佳内存、速度和维护)是使用@MapsId:

@Getter
@Setter
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@OneToOne(mappedBy = "person", fetch = FetchType.LAZY)
private Department department;
}

@Getter
@Setter
@Entity
public class Department {
@Id // Note no generation
private Long id;

private String name;

@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id", foreignKey = @ForeignKey(name = "department_belongs_to_person"))
private Person person;
}

这里 Department 是拥有关系(拥有通常意味着它在数据库中会有包含 FK 的列,但这里它们只是共享主键)并拥有 FK,将其 PK 绑定(bind)到 Person 生成的 PK。

请注意,关系是 OneToOne、双向的,共享 PK 为 FK。这被认为是最佳实践,但有一个小缺点,即必须编写一个 getter。 :)

来源:https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/

另外 - 我强烈建议花几天时间阅读该网站上的帖子,甚至在设计比几张表更大的东西之前实现其中的一些帖子。 :)

编辑

我在这里可能是错的(我现在确信 - 看评论),但据我所知,保持 ID 相等并不是 JPA 指定的。它可以指定的内容基本上是:

“嘿,你们(Person,Department)是兄弟(OneToOne)并且都知道这一点(Person实体中的mappedBy =“person”是双向的)。你将是会生成ID的老兄弟(Person有@GenerateValue) ,你会更年轻,应该有相同的。你将使用这些字段(ID,一个是生成的,第二个不是)来连接(@PrimaryKeyJoinColumn)。”

我想说的是,仅仅因为你说“这连接了你”,并不意味着它们是同步的 - 你必须确保它。

现在说到如何确保它 - @MapsId 被认为是最好的。

如果您正在寻找不同的方法,还可以使用 #setDepartment(Department) 手动将 ID 设置为与其他方法相同,您可以将部门的 ID 设置为与调用人员相同(但这仅在该人员已经有一个ID生成,这基本上打破了这个想法)。

我知道的另一个是使用外部生成器策略。

人:

@Id
@GeneratedValue
private long id;

@OneToOne(mappedBy="person")
private Department department;

部门:

@Id
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="person"))
private long id;

@OneToOne
@PrimaryKeyJoinColumn
private Person person;

现在 - 这使用特定于 hibernate 的注释并且不是纯 JPA。

关于java - @PrimaryKeyJoinColumn 未选择共享 key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53564715/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com