如何使用 JPA/Hibernate 在孩子的 id 中引用父母的 id?

Posted

技术标签:

【中文标题】如何使用 JPA/Hibernate 在孩子的 id 中引用父母的 id?【英文标题】:How to reference a parent's id in a child's id with JPA/Hibernate? 【发布时间】:2016-08-08 21:46:18 【问题描述】:

给定一个表 (MY_TABLE_A),它会在每次新插入时自动增加其 ID(即数据库中的第一条记录的 ID 属性为 1,第二条记录的 ID 属性设置为 2,第三条记录的 ID 属性为ID 属性设置为 3)。我所说的ID是表的主键。

我还有另一个表 (MY_TABLE_B),它引用的是原始表的主键。当我尝试将两者都持久化到我的 Oracle 数据库时,我得到一个 org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save()

我想要完成的事情: 每当我将一个对象持久化到 MY_TABLE_A 时,我希望 MY_TABLE_B 插入一个具有与 MY_TABLE_A 相同 ID 的对象,因为它是自动递增的(将'在插入之前不知道下一个值是什么)。澄清一下,表 A 中的一个 id 在表 B 中应该只有一个匹配的 ID

以下是我的代码的一些 sn-ps:

头等舱:

@Entity
@Table(name = "MY_SCHEMA.MY_TABLE_A")
@Component
public class FirstClass implements Serializable 

    @Id
    @SequenceGenerator(name = "MY_SEQ", sequenceName = "MY_SCHEMA.MY_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_SEQ")
    @Column(name = "MY_ID")
    private Integer myId;
    // more variables, getters/setters


二等:

@Entity
@Table(name = "MY_SCHEMA.MY_TABLE_B")
@SecondaryTable(name = "MY_SCHEMA.MY_TABLE_A", pkJoinColumns = @PrimaryKeyJoinColumn(name = "MY_ID", referencedColumnName = "MY_ID"))
@Component
public class SecondClass 

    @Id
    @Column(name = "MY_ID")
    private Integer myId;
    // more variables, getters/setters


服务层 sn-p 我在 Oracle 中为每个插入新条目:

firstClassService.insert();
secondClassService.insert();

关于 firstClassService 的insert() 的详细信息:

public void insert() 
        FirstClass obj = new FirstClass();
        getCurrentSession().persist(obj);


insert() 为 secondClassService:

public void insert() 
        SecondClass obj = new SecondClass();
        getCurrentSession().persist(obj);

更新

FirstClass 现在的样子:

@Entity
@Table(name = "MY_SCHEMA.MY_TABLE_A")
@Component
public class FirstClass implements Serializable 

    @Id
    @SequenceGenerator(name = "MY_SEQ", sequenceName = "MY_SCHEMA.MY_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_SEQ")
    @Column(name = "MY_ID")
    @OneToOne(mappedBy = "myId")
    private Integer myId;


二等:

@Entity
@Table(name = "MY_SCHEMA.MY_TABLE_B")
@SecondaryTable(name = "MY_SCHEMA.MY_TABLE_B", pkJoinColumns = @PrimaryKeyJoinColumn(name = "MY_ID", referencedColumnName = "MY_ID"))
@Component
public class SecondClass implements Serializable 

    @Id
    @JoinColumn(name = "MY_ID", referencedColumnName = "MY_ID")
    @OneToOne
    private Integer restRequestId;

【问题讨论】:

【参考方案1】:

映射应该如下:

@Entity
@Table(name = "MY_SCHEMA.MY_TABLE_A")
@Component
public class FirstClass implements Serializable 

    @Id
    @SequenceGenerator(name = "MY_SEQ", sequenceName = "MY_SCHEMA.MY_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_SEQ")
    @Column(name = "MY_ID")
    private Long myId;

    @OneToOne(mappedBy = "firstClass", cascade = CascadeType.ALL)
    private SecondClass secondClass;


@Entity
@Table(name = "MY_SCHEMA.MY_TABLE_B")
@Component
public class SecondClass implements Serializable 

    @Id
    @JoinColumn(name = "MY_ID", referencedColumnName = "MY_ID")
    @OneToOne
    private FirstClass firstClass;

设置 Cascade 选项后,您只需调用保存 firstClass:关联的 secondClass 将自动持久化 - 假设您在内存模型中设置了关系的两侧,即

firstClass.setSecondClass(secondClass);
secondClass.setFirstClass(firstClass);

【讨论】:

谢谢 - 这有助于我更好地理解这个概念。我现在面对org.hibernate.AnnotationException: Unknown mappedBy in: mypackage.mysubpackage.FirstClass.secondClass, referenced property unknown: mypackage.mysubpackage.SecondClass.firstClass?此时可能是配置问题吗? 确保类在持久化 xml 中正确注册,检查两个类中是否存在“实体”注释。此外,我可以告诉您,您正在使用不太复杂的类来表示您的问题,查看实际的类会很有用。 谢谢大家!它现在完美运行。我把你们每个人的东西拼凑在一起,我更多地研究了文档,这一切都很有意义:) @DanielArechiga【参考方案2】:

@GeneratedValue(strategy=GenerationType.IDENTITY)添加到第二类的id。

@Id
@Column(name = "MY_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer myId;
// more variables, getters/setters

【讨论】:

添加时出现以下错误:org.hibernate.MappingException: org.hibernate.dialect.identity.IdentityColumnSupportImpl does not support identity key generation 如果有帮助,我的 id 没有在第二类使用的表中设置为自动递增。 见这里:***.com/questions/24009042/…【参考方案3】:

从您的描述来看,您似乎有一个 ManytoOne 关系,因为您的表 B 引用了表 A,所以说 A 有一个 B 列表是合乎逻辑的,所以为什么不利用 ORM 的实际含义,为什么不保留A 中的引用,例如:

@OneToMany(mappedBy="aa")
private List<B> bs;

并在另一个实体中使用注释:

@ManyToOne
@JoinColumn(name = "myId" , referencedColumnName = "id")
private A aa;

结合 Jens 的建议,请参阅 OracleDialect does not support identity key generation

【讨论】:

我为这个问题添加了更多背景信息,这将是一对一的关系,因为表 A 中只有一个 id 在表 B 中应该有一个对应的单个 id(即表 A 中的 ID 100 应该有表B中只有一个ID为100) 同样适用,只需删除 List 声明并将其作为单个 bean 属性执行,将 oneToMany 和 ManyToOne 分别更改为 OneToOne 试图准确地添加它,但得到一个org.hibernate.AnnotationException: @Column(s) not allowed on a @OneToOne property: 抱歉,我已经在这几个小时了,它只是没有点击我。我更新了我的问题以反映您和 Jens 推荐的代码以及任何相关链接

以上是关于如何使用 JPA/Hibernate 在孩子的 id 中引用父母的 id?的主要内容,如果未能解决你的问题,请参考以下文章

Maven + Spring Boot + JPA + Hibernate 项目有问题吗?

如何使用 JPA 和 Hibernate 在 UTC 时区中存储日期/时间和时间戳

如何使用 JPA+Hibernate 在 json 结果中包含连接列

如何在pojo中用jpa或hibernate映射json字段?

如何在 JPA/Hibernate 中执行本机 SQL 脚本?

Spring Boot / JPA / Hibernate,如何根据 Spring 配置文件切换数据库供应商?