2009-10-16 51 views
1
Hibernate註解生成查詢

還是躲開它的攻擊與Hibernate ...產生SQLGrammarException

我使用Hibernate的註解,而不是我的豆子的hbm.xml文件,但我目前運行到一個問題,即Hibernate生成的SQL引用不存在的數據庫列。

舉例來說,這裏是代碼:

Query q = session.createQuery("FROM Status ORDER BY post_date DESC"); 

(據檢索Status對象的列表,從最近下令至少最近,每個Status對象包含它自己Comment對象列表.. 。是的,認爲Facebook的職位)

這裏是它生成的查詢:

Hibernate: select status0_.pid as pid1_, status0_.content as content1_, status0_.owner_uid as owner5_1_, status0_.parent_pid as parent6_1_, status0_.post_date as post4_1_, status0_.type as type1_ from POSTS status0_ order by post_date DESC limit ? 

問題在該查詢中,它引用status0_.owner_uidstatus0_.parent_pid,但這些字段不存在於數據庫中。當我手動更改查詢以分別使用status0_.ownerstatus0_.parent,並將其提供給MySQL時,它完美工作。

涉及四個類。

一個User,它沒有在系統中別的概念(以下相關領域):

@Entity 
@Embeddable 
@Table(name="USERS") 
public class User { 

    @Id 
    @GeneratedValue 
    @Column(name="uid") 
    private Integer uid; 

... 
} 

一個Post,爲CommentStatus一個抽象的超類存儲在同一個表中,並通過差異化列type(下面相關字段):

@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(
    name="type", 
    discriminatorType=DiscriminatorType.STRING 
) 
@MappedSuperclass 
@Entity 
@Embeddable 
@Table(name="POSTS") 
public abstract class Post { 

    @Id 
    @GeneratedValue 
    @Column(name="pid") 
    private Integer pid; 

    @ManyToOne 
    @Embedded 
    private Post parent; 

    @ManyToOne 
    @Embedded 
    private User owner; 

    @Column(name="post_date") 
    private Timestamp postDate; 

    @Column(name="content") 
    private String content; 

    @Column(name="type", updatable=false) 
    private String type; 
    ... 
} 

Status甲類,子類Post;設置parent爲null,還包含Comment個表(見下面相關領域):

@Entity 
@Table(name="POSTS") 
@DiscriminatorValue("status") 
public class Status extends Post { 

    @OneToMany(mappedBy="parent") 
    @OrderBy("postDate asc") 
    private List<Comment> children; 
    ... 
} 

一個Comment類,繼承Post;有一個非空parent(貼在下面整個班級):

@Entity 
@DiscriminatorValue("comment") 
@Table(name="shannonq_posts") 
public class Comment extends Post { 
    // this class is literally empty 
} 

總結:我不知道爲什麼Hibernate是爲了追加嵌入類的ID添加到查詢,結果一個不存在的列。理想情況下,我希望已將@Column(name="parent")註釋添加到這些字段,但似乎Hibernate不允許將此特定註釋標記爲@ManyToOne

任何幫助表示讚賞!謝謝!如果我手動更改數據庫中的列以匹配Hibernate產生的列,我會得到另一個錯誤:Cannot instantiate abstract class or interface: Post。很明顯,我的配置不正確。 :P

回答

1

對於ManyToOne關聯,Hibernate的默認命名策略將使用您的字段名稱並使用下劃線附加關聯表的PK列。

因此,對於Post(狀態的超類),您將owner_uidparent_pid作爲列名,因爲uidpid分別是PK列名。

您可以通過使用@JoinColumn批註覆蓋此:

@ManyToOne 
@JoinColumn(name = "parent") 
private Post parent; 

@ManyToOne 
@JoinColumn(name = "owner") 
private User owner; 

或實現自己的NamingStrategy(休眠特定的,不建議初學者:-))

在一個側面說明,@嵌入表示您想要將給定的實體映射爲組件(基本上是該同一表的一部分)。將@ManyToOne和@Embedded放在同一個屬性上(或應該是)非法。

+0

我應該剛開始通知你,當我有一個休眠問題:)問題修復!再次感謝你! – Magsol 2009-10-16 23:55:38

+0

不用擔心,這就是我在Hibernate標籤中閒逛的原因:-) – ChssPly76 2009-10-17 00:02:19