在 Hibernate 中,你可以有一个组合键,其中一个值是数据库生成的吗?
In Hibernate, can you have a composite key where one value is database generated
我有一个带有复合键的 table 数据库,其中一个值是在数据库中生成的,另一个是基于父 class 设置的。我正在尝试在休眠中实现它。我已经看到大量与此矛盾的文章,可能基于不同的版本。对于 Hibernate 4.3,我该怎么做?
这是似乎最合理但行不通的解决方案。数据库最大的限制是要生成的key不应该在insert
中传入
内部邮件列表class
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name="mailLists", column=@Column(name="Mail_Lists", nullable=false) ),
@AttributeOverride(name="ien", column=@Column(name="IEN", nullable=false, insertable=false, updatable=false) ) } )
public MailListsSubscriberId getId() {
return this.id;
}
单独的复合 ID class
@Embeddable
public class MailListsSubscriberId implements java.io.Serializable {
private int mailLists;
private int ien;
@Column(name="Mail_Lists", nullable=false)
public int getMailLists() {
return this.mailLists;
}
...
@Generated(GenerationTime.ALWAYS)
@Column(name="IEN", nullable=false, insertable=false, updatable=false)
public int getIen() {
return this.ien;
}
...
日志
Caused by: org.hibernate.id.IdentifierGenerationException: null id generated for:class edu.ucdavis.vmth.vmacs.persistence.model.MailListsSubscriber
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:120)
at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:271)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:251)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:189)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:886)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:868)
at org.hibernate.engine.spi.CascadingActions.cascade(CascadingActions.java:277)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118)
at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:474)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:343)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:186)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
问题是您的数据库模型不正确,无法与 hibernate 或任何其他 ORM 一起使用。提示是你在问题中所说的
The big limitation on the database is that the key to be generated shouldn't be passed in the update
这意味着生成的列不是键的一部分,否则您将需要它,否则它不是标识符的一部分。
如果您想了解为什么会这样,您可以阅读 Object-Relational impedance mismatch。
如果您正在处理设计不佳的遗留架构并且您无法更改它,我建议您放弃休眠并使用类似 MyBatis 的东西。
编辑
好的,在澄清不能在 insert 而不是 update 上传递密钥之后,有一个解决方案(我'我从未使用过,所以希望它会起作用)。 Hibernate 支持一种叫做 select
的 generator 类型,它就是为这种情况而存在的。
例如,您可以尝试使用以下注释注释 ien
列(示例取自 Hibernate docs)
@Id
private int mailLists;
@Id @GeneratedValue(generator="trigger-generated")
@GenericGenerator(
name="trigger-generated",
strategy = "select",
parameters = @Parameter(name="key", value = "surrogateIdColumnName")
)
private String ien;
奇怪 事情是,为了使休眠能够检索生成的密钥,它需要 select 行...为此,它需要知道另一列用作代理键。在上面的例子中,table 必须有一个名为 surrogateIdColumnName
的列,它是唯一的。
理想情况下,如果您可以更新架构,最好为 table 分配一个具有自动增量值的单个 id 列,并使另一个键 (mailList + ien) 成为唯一键。
我有一个带有复合键的 table 数据库,其中一个值是在数据库中生成的,另一个是基于父 class 设置的。我正在尝试在休眠中实现它。我已经看到大量与此矛盾的文章,可能基于不同的版本。对于 Hibernate 4.3,我该怎么做?
这是似乎最合理但行不通的解决方案。数据库最大的限制是要生成的key不应该在insert
中传入内部邮件列表class
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name="mailLists", column=@Column(name="Mail_Lists", nullable=false) ),
@AttributeOverride(name="ien", column=@Column(name="IEN", nullable=false, insertable=false, updatable=false) ) } )
public MailListsSubscriberId getId() {
return this.id;
}
单独的复合 ID class
@Embeddable
public class MailListsSubscriberId implements java.io.Serializable {
private int mailLists;
private int ien;
@Column(name="Mail_Lists", nullable=false)
public int getMailLists() {
return this.mailLists;
}
...
@Generated(GenerationTime.ALWAYS)
@Column(name="IEN", nullable=false, insertable=false, updatable=false)
public int getIen() {
return this.ien;
}
...
日志
Caused by: org.hibernate.id.IdentifierGenerationException: null id generated for:class edu.ucdavis.vmth.vmacs.persistence.model.MailListsSubscriber
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:120)
at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:271)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:251)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:189)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:886)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:868)
at org.hibernate.engine.spi.CascadingActions.cascade(CascadingActions.java:277)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118)
at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:474)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:343)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:186)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
问题是您的数据库模型不正确,无法与 hibernate 或任何其他 ORM 一起使用。提示是你在问题中所说的
The big limitation on the database is that the key to be generated shouldn't be passed in the update
这意味着生成的列不是键的一部分,否则您将需要它,否则它不是标识符的一部分。
如果您想了解为什么会这样,您可以阅读 Object-Relational impedance mismatch。
如果您正在处理设计不佳的遗留架构并且您无法更改它,我建议您放弃休眠并使用类似 MyBatis 的东西。
编辑
好的,在澄清不能在 insert 而不是 update 上传递密钥之后,有一个解决方案(我'我从未使用过,所以希望它会起作用)。 Hibernate 支持一种叫做 select
的 generator 类型,它就是为这种情况而存在的。
例如,您可以尝试使用以下注释注释 ien
列(示例取自 Hibernate docs)
@Id
private int mailLists;
@Id @GeneratedValue(generator="trigger-generated")
@GenericGenerator(
name="trigger-generated",
strategy = "select",
parameters = @Parameter(name="key", value = "surrogateIdColumnName")
)
private String ien;
奇怪 事情是,为了使休眠能够检索生成的密钥,它需要 select 行...为此,它需要知道另一列用作代理键。在上面的例子中,table 必须有一个名为 surrogateIdColumnName
的列,它是唯一的。
理想情况下,如果您可以更新架构,最好为 table 分配一个具有自动增量值的单个 id 列,并使另一个键 (mailList + ien) 成为唯一键。