![](/img/trans.png)
[英]Hibernate Annotations - @MappedSuperclass How to override column identifier
[英]Override Hibernate Annotations
我正在開發一個使用Hibernate並連接到Oracle實例的Java應用程序。 另一個客戶端希望使用相同的應用程序,但要求它在MS SQL Server上運行。 我想避免對現有注釋進行更改,而是創建一個xml文件包,我們可以根據環境將其放入。
一種方法是使用JPA XML配置覆蓋現有的類注釋。 但是,JPA不支持通用生成器,由於我們的遺留數據庫的結構,這是一個要求。 我正在研究的另一種方法是使用Hibernate XML配置重新映射整個類並訪問generator
xml標記。 這個解決方案有一些問題:
org.hibernate.AnnotationException: Use of the same entity name twice
) 有沒有人有使用Hibernate XML配置文件覆蓋注釋的經驗,或者JPA是唯一的方法嗎?
在Oracle中,序列用於在將新記錄插入數據庫時生成唯一ID。 然后以下列方式注釋id:
@Id
@GeneratedValue(generator="EXAMPLE_ID_GEN", strategy=GenerationType.SEQUENCE)
@SequenceGenerator(name="EXAMPLE_ID_GEN", sequenceName="SEQ_EXAMPLE_ID")
@Column(name = "EXAMPLE_ID")
public String getExampleId() {
return this.exampleId;
}
但是,MS SQL Server沒有Sequences的概念(思想差異)。 因此,您可以使用表生成器來模擬序列。
@Id
@GeneratedValue(generator="EXAMPLE_ID_GEN", strategy=GenerationType.TABLE)
@TableGenerator(name="EXAMPLE_ID_GEN", tableName="SEQUENCE", valueColumnName="VALUE", pkColumnName="SEQUENCE", pkColumnValue="EXAMPLE_ID")
public String getExampleId() {
return this.exampleId;
}
兩種不同類型數據庫的兩種不同配置。 請記住,這是一個遺留數據庫,我們不會重寫我們的應用程序來支持SQL Server身份,SQL Server的本機ID生成器(也需要不同的注釋)。
為了解決這個問題,我研究了使用Hibernate的@GenericGenerator
並將其指向我自己的一個類,它創建了org.hibernate.id.SequenceGenerator
(或類似的東西)的模型,並通過擴展org.hibernate.id.TableStructure
定義表的結構org.hibernate.id.TableStructure
。
回到我原來的問題 - 使用XML覆蓋是否可以實現這一切?
所以,最后,我發現JPA和Hibernate沒有提供我正在尋找的開箱即用功能。 相反,我創建了一個自定義生成器,它檢查數據庫方言並適當地設置TableStructure。 當我探索所有選項時,我最終使用了Hibernate的@GenericGenerator
注釋。 這是Id生成注釋的示例:
@Id
@GeneratedValue(generator="EXAMPLE_ID_GEN")
@GenericGenerator(name = "EXAMPLE_ID_GEN", strategy="com.my.package.CustomIdGenerator", parameters = {
@Parameter(name = "parameter_name", value="parameter_value")
})
public String getExampleId() {
return this.exampleId;
}
此解決方案需要使用新的Id生成器修改每個Hibernate實體。
我認為如果在配置SessionFactory
時不使用AnnotationConfiguration
,則會省略注釋。
所以,使用Configuration
。
對於您的生成器問題(解決方案通常是“使用本機生成器”但由於使用遺留數據庫而無法為您工作),您可以擴展SQLServerDialect並覆蓋getNativeIdentifierGeneratorClass以返回(可能是自定義的) )生成器,為您的遺留數據庫提供所需的功能。
我之前在Grails(GORM)應用程序中遇到了混合n-match遺留與新模式/數據庫的需求,當然它正在運行Hibernate 3。
不會說“你做錯了” - 但是我會將JPA @Annotations保留到像@Entity和@Column這樣的基礎知識中,並將它留給Hibernate 方言 ,這也是在XML配置文件中指定的。
您可以嘗試將Oracle10gDialect子類化為一個為所有表分配序列生成器的子類,而不是Sybase的子類。
請參閱此帖子 ,了解如何實現此目的。
更新:詹姆斯和我建議(幾乎在同一分鍾內)是設置persistence.xml文件的多個持久性單元部分。
這允許使用@Entity和@Id而不提供類中的詳細信息。 詳細信息來自hibernate.dialect
屬性。 我建議繼承Oracle10gDialect(和james SQLServerDialect) - 那些會選擇表命名,id生成器策略等。
請參閱 - > https://forum.hibernate.org/viewtopic.php?f=1&t=993012
如果重寫HBM XML文件中的注釋,則可以維護兩組這樣的XML,並通過Hibernate的映射指令選擇要使用的XML。 我在Hibernate Core中完成了這個,但是在J2EE / JPA環境中沒有這樣做,所以我不知道在這方面是否有任何問題。
最大的缺點是刪除所有注釋並在XML中重建它們可能需要做很多工作。
就我而言:
機架和插槽是具有自定義ID生成器的實體。 我正在使用單向一對一映射。 維度表將使用自動生成的自定義ID作為多個表的外鍵來保存數據(例如,此處為機架和插槽)。 我的模式如下所示:Rack ------> Dimension <----------- Slot其中Dimension將保存帶有生成ID的Rack和Slot表的數據。
這里關注的是,當我保存這樣的數據: -
Rack rack = new Rack(params);
Dimension dim = new Dimension(params);
rack.setDimension(dim);
session.save(rack);
在Rack和Dimension Tables中使用相同的Autogenerated ID成功保存數據。
但是當我保存Slot表的數據時:
Slot Slot = new Slot(params);
Dimension dim = new Dimension(params);
slot.setDimension(dim);
session.save(slot);
它顯示錯誤消息: -
attempted to assign id from null one-to-one property: rack
我可以在保存Slot和Dimension的數據時將動態屬性名稱作為“slot”傳遞,並在保存Rack和Dimension的數據時將其傳遞給“rack”。
@GenericGenerator(name = "foreign", strategy = "foreign", parameters = {
@Parameter(name = "property", value = "slot"),
@Parameter(name = "property", value = "rack")})
Rack.java
@Entity
@Table(name="tablename")
@GenericGenerator(name = "customseq", strategy = "CustomIdGenerator")
public class Rack {
@Id
@GeneratedValue(generator = "customseq")
@Column(name = "uni_id")
private String id;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private Dimension dimension;
// Getters and Setters
}
Slot.java
@Entity
@Table(name="tablename")
@GenericGenerator(name = "customseq", strategy = "CustomIdGenerator")
public class Rack {
@Id
@GeneratedValue(generator = "customseq")
@Column(name = "uni_id")
private String id;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private Dimension dimension;
// Getters and Setters
}
Dimension.java
public class Dimension implements Serializable{
@Id
@Column(name = "systemid")
@GeneratedValue(generator = "foreign")
@GenericGenerator(name = "foreign", strategy = "foreign", parameters = {
@Parameter(name = "property", value = "slot"),
@Parameter(name = "property", value = "rack")})
private String systemid;
@OneToOne(mappedBy = "dimension", fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private Rack rack;
@OneToOne(mappedBy = "dimension", fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private Slot slot;
// Getters and Setters
}
我會說,如果您的注釋是特定於數據庫的,那么您做錯了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.