Hibernate Annotations生成生成SQLGrammarException的查询

时间:2009-10-16 23:34:23

标签: hibernate exception annotations

还是用Hibernate把它搞定了......

我正在为我的bean使用Hibernate-Annotations而不是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时,它可以很好地工作。

涉及四个课程。

A User,系统中没有任何其他概念(下面的相关字段):

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

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

...
}

PostCommentStatus的抽象超类,存储在同一个表格中,并通过列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;有一个非null 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 个答案:

答案 0 :(得分:1)

Hibernate的ManyToOne关联的默认命名策略使用您的字段名称,并使用下划线附加关联表的PK列。

因此,对于Post(状态的超类),您将owner_uidparent_pid作为列名,因为uidpid是各自的PK列名称。

您可以使用@JoinColumn注释覆盖它:

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

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

或实施自己的NamingStrategy(特定于Hibernate,不推荐给初学者:-))

另外,@ Embrite表示您要将给定实体映射为组件(基本上是同一个表的一部分)。将@ManyToOne和@Embedded放在同一财产上是(或应该)是非法的。