2009-09-17 28 views
1

我正在爲數據庫視圖的hibernate實體映射工作;當我對它進行標準查詢時,hibernate正在生成錯誤的SQL。任何幫助搞清楚我的映射的問題將不勝感激!錯誤的SQL使用Hibernate註解的視圖對象

我有兩個映射的實體,我試圖從數據庫視圖中獲取;該視圖沒有其他列,只是每個實體的FK。其中一個FK可以被視爲主鍵,因爲該視圖對每個主要實體都有一行。所以,我的觀點DB模式是這樣的:

primary(primary_id, some_other_fields) 
history(history_id, primary_id, some_other_fields) 
view_latest_status_history(primary_id, history_id) 

注意視圖的使用,因爲我想挑出只有最新的歷史記錄每個主,不是所有的映射歷史記錄。以下是我用於視圖的對象,包含實體註釋:

@Entity 
@org.hibernate.annotations.Entity(dynamicUpdate = true) 
@Table(name = "view_latest_status_history") 
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
public class ViewLatestStatusHistoryRow implements Serializable { 
    private Primary primary; 
    private History history; 

    /** 
    * @return Returns the history. 
    */ 
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY) 
    @JoinColumn(name = "history_id", nullable = true) 
    @AccessType("field") 
    public History getHistory() { 
     return history; 
    } 

    //equals() and hashCode() implementations are omitted 

    /** 
    * @return Returns the primary. 
    */ 
    @Id 
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY) 
    @JoinColumn(name = "primary_id", nullable = false) 
    @AccessType("field") 
    public Primary getPrimary() { 
     return primary; 
    } 
} 

主對象和歷史對象都具有完整的工作實體註釋。

我的標準設置:

criteria.add(Restrictions.in("primary", [collection of primary objects])); 
criteria.setFetchMode("primary", FetchMode.JOIN); 
criteria.setFetchMode("history", FetchMode.JOIN); 

而(錯誤)生成的SQL:

select this_.primary as primary78_1_, this_.primary_id as prim2_78_1_, primary2_.history_id as unique1_56_0_, ...history fields 
from DB_CATALOG.dbo.view_latest_status_history this_ 
left outer join DB_CATALOG.dbo.history primary2_ on this_.primary_id=primary2_.primary_id 
where this_.specChange in (?, ?...) 

編輯我們項目的數據庫架構的具體細節時,我可能已經打亂了幾件事情,但重點是'select'子句中的第一個字段是錯誤的:

this_.primary(view_latest_status_history.primary)不是字段;該字段應該被稱爲primary_id。我認爲這可能與主字段上的@Id註釋有關?任何想法如何解決這一問題?如果我刪除了@Id,我得到一個錯誤,告訴我該實體沒有主鍵。

更新:

我不再使用一個連接表表示法(如下面所建議的)地圖的視圖作爲一個字段。註釋已被修改如下。此解決方案在HQL中正常工作,並在啓用hbm2ddl時生成預期模式,但我沒有使用條件查詢重新測試它。

@Entity 
@Table(name = "view_latest_status_history") 
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
public class ViewLatestStatusHistoryRow implements Serializable { 
    private String id; 
    private Primary primary; 
    private History history; 

    /** 
    * @return Returns the history. 
    */ 
    @OneToOne(optional = true) 
    @JoinColumn(name = "history_id", nullable = true) 
    @AccessType("field") 
    public History getHistory() { 
     return history; 
    } 

    //equals() and hashCode() implementations are omitted 

    @Id 
    @Column(name = "primary_id", nullable = false) 
    @Override 
    @AccessType(value = "field") 
    public String getId() { 
     return id; 
    } 

    /** 
    * @return Returns the primary. 
    */ 
    @PrimaryKeyJoinColumn(name = "primary_id", referencedColumnName = "unique_id") 
    @OneToOne(optional = false) 
    @AccessType("field") 
    public Primary getPrimary() { 
     return primary; 
    } 
} 

回答

1

這肯定是由於@Id註釋 - primary_id是不是在這種情況下,一個主鍵。你也不能在同一個屬性上實際擁有@Id和@ManyToOne。

讓我問你這個問題 - 你爲什麼把ViewLatestStatusHistoryRow作爲一個實體來開始?這不像你永遠堅持下去。考慮將主要(多對一)直接(作爲只讀)映射到最新的歷史記錄,並將視圖用作連接表。

+0

我會嘗試將它映射到主要,並標記爲答案,如果它的工作!感謝您的快速回復。你知道我在一般情況下如何處理這個問題,以與其他領域的觀點?另外,如何在添加新(最新)歷史記錄時確保該屬性在主對象上更新? – RMorrisey

+0

不必更新屬性,因爲您不會維護它。你需要使用JoinTable來映射它:http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e1177 就「視野與領域」而言,如果你需要爲了映射它,你需要將它映射爲實體。這意味着有一個**真正的**主鍵,而不是偶然發生的事情:-)您可以使用複合ID來映射包含多列的PK,但可能會產生難看的副作用。查看複合標識符的Hibernate文檔以獲取更多詳細信息。 – ChssPly76

+0

這讓我可以消除n + 1選擇問題,並且可以大大加快批量處理速度,從而實現幾千種初選。謝謝=) – RMorrisey