2012-05-16 20 views
1

以下是我無法找到解決方案的問題,我想這可能是不可能的,或者我將整個想法帶向錯誤的方向。將已加入的JPA繼承導入到已有的數據庫中

起初我JPA體系中的一部分是像這樣:

@MappedSuperclass 
public abstract class AbstractEntity { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    protected Long id; 
    ..... 
} 

@Audited 
@Entity 
@Table(name = "T_MEETING") 
public class Meeting extends AbstractEntity implements Groupable {...} 

@Audited 
@Entity 
@Table(name = "T_QUESTION") 
public class Question extends AbstractEntity implements Groupable {...} 

這個數據庫已經使用了一段時間,直到需要對某些對象的自定義字段出現。

我決定去follwing路線 - 把一個抽象的實體爲對象的基帶定製字段:

@Audited 
@Entity 
@Table(name = "T_CF_OBJECT") 
@Inheritance(strategy = InheritanceType.JOINED) 
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID") 
public abstract class EntityWithCustomFields extends AbstractEntity {...} 

@Audited 
@Entity 
@Table(name = "T_QUESTION") 
public class Question extends EntityWithCustomFields implements Groupable {...} 

@Audited 
@Entity 
@Table(name = "T_MEETING") 
public class Meeting extends EntityWithCustomFields implements Groupable {...} 

我曾嘗試不同的選擇,並始終有一個問題:

  1. JPA提供者(在我的情況下休眠),我猜,首先插入父親,因此它的CF_OBJECT_IDnull

    Hibernate:insert i ?t_cf_object(id,cf_object_id)values(null,?) Hibernate:insert into t_meeting(active,date,c_group,last_notification_date,only_for_members,place,questions_order,subject,update_date,id)values(?,?,?,? ?,?,?,?,?,?)

  2. 如果我忽略對基礎機構@PrimaryKeyJoinColumn批註,則其IdId S上的後代被用作連接列,它會導致什麼是子類表沒有相同的ID。這在開始時很好,但我們已經在兩個表中都有大量的記錄,並且它們在id列中具有相同的值。在表中更改id s是不可選的。

什麼是在我的情況下使用繼承的正確方法,所以它儘可能無縫地進入?我很高興知道如何讓hibernate首先保存子類實例,然後將其id傳遞給持久化的超類。這需要註解,對吧?

編輯:至於建議,使用@MappedSuperclass

我真的不能使用@MappedSuperClass原因如下。父類EntityWithCustomFields用於指012xx類中的ManyToOne關係。在它的代碼看起來像如下:

@Entity 
@Audited 
@Table(name = "T_CF_VALUES") 
public class CustomFieldValue extends AbstractEntity { 
    @ManyToOne 
    @JoinColumn(name = "customFieldObject", nullable = false) 
    private EntityWithCustomFields customFieldObject; 
    .... 
} 
@Audited 
@Entity 
@Table(name = "T_CF_OBJECT") 
@Inheritance(strategy = InheritanceType.JOINED) 
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID") 
public abstract class EntityWithCustomFields extends AbstractEntity { 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "customFieldObject", cascade = CascadeType.ALL) 
    private List<CustomFieldValue> customFields; 
    .... 
} 

我不認爲@MappedSuperclass可以在這類東西可以用做。

回答

0

在我看來,你不想在這裏實體繼承,而是爲你的實體使用自定義字段的附加映射超類。

當你有一個真實的is-a函數關係時,必須使用實體繼承。例如,一張發票可能有一個產品清單,產品實體就是繼承樹(蔬菜,肉類,衣服等)的根。在這種情況下,Vegetable是一種產品,當然兩種產品可能沒有相同的ID,因爲Price實體可以通過外鍵引用產品,如果兩種產品具有相同的ID,根本不工作。

就你而言,具有自定義字段的實體完全不相關。他們只是碰巧有共同的領域,你想通過把這些共同的領域放入一個超類來考慮這一點。這就是MappSuperclass的用途。而這些自定義字段應該在每個實體表中重複。無論如何,這將比加入的繼承更有效率(這會導致更多的查詢,更復雜且難以優化查詢)。

+0

我已經回答了你對我自己問題的回答的評論 – EvgeniySharapov