【问题标题】:Hibernate Annotations generating query that produces SQLGrammarExceptionHibernate Annotations 生成产生 SQLGrammarException 的查询
【发布时间】:2009-10-16 23:34:23
【问题描述】:

仍在与 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 时,它可以完美运行。

涉及四个类。

一个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 并且还包含 Comments 的列表(下面的相关字段):

@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

【问题讨论】:

    标签: hibernate exception annotations


    【解决方案1】:

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

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

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

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

    或通过实现您自己的 NamingStrategy(Hibernate 特定,不建议初学者使用 :-))

    附带说明,@Embedded 表示您希望将给定实体映射为组件(基本上是同一张表的一部分)。将@ManyToOne 和@Embedded 放在同一个属性上是(或应该是)非法的。

    【讨论】:

    • 当我有 Hibernate 问题时,我应该开始向您发送消息 :) 问题已解决!再次感谢您!
    • 别担心,这就是我在 Hibernate 标签中闲逛的原因 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    • 1970-01-01
    相关资源
    最近更新 更多