Hibernate:如何设置具有相同顺序生成主键的两个表之间的关系?
Hibernate: How to set the relations between two tables with the same sequence generated primary key?
我有 2 个 table,T_PLN 和 T_PLN_CST_PRD
生成器 (M2M.Q_PLN_ID) 在数据库 (Oracle) 中定义,应用作两个 table 的主键。
在保存一个新计划(其中包含一个 CostPeriod)时,我希望生成器为 T_PLN 创建一个新的主键并将其也用作 T_PLN_CST_PRD 中的主键。
Table T_PLN
PLN_ID // 序列生成的主键(long)
// 更多列
Table T_PLN_CST_PRD
PLN_ID // 主键 - 应该与 T_PLN table 中的主键相同
// 更多列
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "PLN_ID", table = "T_PLN_CST_PRD")
CostPeriod costPeriod;
...
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@Column(name = "PLN_ID")
Long planId;
...
}
上面的代码缺少连接两个主键的内容,但我不确定是什么...
我尝试了各种关系(@OneToOne 与 mappedBy,@JoinColumn,将 Plan 添加为 T_PLN_CST_PRD 的成员..)但由于种种原因无法正常工作:
IdentifierGenerationException:此 class 的 ID 必须在调用 save() 之前手动分配:
IdentifierGenerationException:试图从 null 一对一分配 id 属性
和其他人...
还尝试了以下解决方案:
OneToOne between two tables with shared primary key
运气不好。
这种关系应该怎么定义?
我认为您缺少双向一对一共享主键模型的 @PrimaryKeyJoinColumn
和 MapsId
。
你能试试下面的映射吗:
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL})
@PrimaryKeyJoinColumn
//OR
//Instead of above @OneToOne and @PrimaryKeyJoinColumn use below:
//@OneToOne(mappedBy="plan", cascade = {CascadeType.ALL})
CostPeriod costPeriod;
...
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@Column(name = "PLN_ID")
Long planId;
@OneToOne
@JoinColumn(name = "id")
@MapsId
private Plan plan;
...
}
保存时:
Plan p = new Plan();
CostPeriod cp = new CostPeriod();
p.costPeriod = cp;
cp.plan = p;
session.persist(p);
假设 JPA 2+,那么您可以轻松地将其映射如下:
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL}, mappedBy = "plan")
CostPeriod costPeriod;
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "PLN_ID")
Plan plan;
}
确保在持久化之前设置了关系的双方。
plan.setCostPeriod(costPeriod);
costPeriod.setPlan(plan);
我有 2 个 table,T_PLN 和 T_PLN_CST_PRD 生成器 (M2M.Q_PLN_ID) 在数据库 (Oracle) 中定义,应用作两个 table 的主键。
在保存一个新计划(其中包含一个 CostPeriod)时,我希望生成器为 T_PLN 创建一个新的主键并将其也用作 T_PLN_CST_PRD 中的主键。
Table T_PLN PLN_ID // 序列生成的主键(long) // 更多列
Table T_PLN_CST_PRD PLN_ID // 主键 - 应该与 T_PLN table 中的主键相同 // 更多列
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "PLN_ID", table = "T_PLN_CST_PRD")
CostPeriod costPeriod;
...
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@Column(name = "PLN_ID")
Long planId;
...
}
上面的代码缺少连接两个主键的内容,但我不确定是什么...
我尝试了各种关系(@OneToOne 与 mappedBy,@JoinColumn,将 Plan 添加为 T_PLN_CST_PRD 的成员..)但由于种种原因无法正常工作:
IdentifierGenerationException:此 class 的 ID 必须在调用 save() 之前手动分配:
IdentifierGenerationException:试图从 null 一对一分配 id 属性
和其他人...
还尝试了以下解决方案: OneToOne between two tables with shared primary key 运气不好。
这种关系应该怎么定义?
我认为您缺少双向一对一共享主键模型的 @PrimaryKeyJoinColumn
和 MapsId
。
你能试试下面的映射吗:
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL})
@PrimaryKeyJoinColumn
//OR
//Instead of above @OneToOne and @PrimaryKeyJoinColumn use below:
//@OneToOne(mappedBy="plan", cascade = {CascadeType.ALL})
CostPeriod costPeriod;
...
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@Column(name = "PLN_ID")
Long planId;
@OneToOne
@JoinColumn(name = "id")
@MapsId
private Plan plan;
...
}
保存时:
Plan p = new Plan();
CostPeriod cp = new CostPeriod();
p.costPeriod = cp;
cp.plan = p;
session.persist(p);
假设 JPA 2+,那么您可以轻松地将其映射如下:
@Entity
@Table(schema = "M2M", name = "T_PLN")
public class Plan {
@Id
@SequenceGenerator(name = "m2mPlanId", sequenceName = "M2M.Q_PLN_ID")
@GeneratedValue(generator = "m2mPlanId")
@Column(name = "PLN_ID")
Long id;
@OneToOne(cascade = {CascadeType.ALL}, mappedBy = "plan")
CostPeriod costPeriod;
}
@Entity
@Table(schema = "M2M", name = "T_PLN_CST_PRD")
public class CostPeriod {
@Id
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "PLN_ID")
Plan plan;
}
确保在持久化之前设置了关系的双方。
plan.setCostPeriod(costPeriod);
costPeriod.setPlan(plan);