如何使用 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字段?