还是用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_uid
和status0_.parent_pid
,但这些字段在数据库中不存在。当我手动更改查询以分别使用status0_.owner
和status0_.parent
并将其提供给MySQL时,它可以很好地工作。
涉及四个课程。
A User
,系统中没有任何其他概念(下面的相关字段):
@Entity
@Embeddable
@Table(name="USERS")
public class User {
@Id
@GeneratedValue
@Column(name="uid")
private Integer uid;
...
}
Post
,Comment
和Status
的抽象超类,存储在同一个表格中,并通过列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
答案 0 :(得分:1)
Hibernate的ManyToOne关联的默认命名策略使用您的字段名称,并使用下划线附加关联表的PK列。
因此,对于Post(状态的超类),您将owner_uid
和parent_pid
作为列名,因为uid
和pid
是各自的PK列名称。
您可以使用@JoinColumn注释覆盖它:
@ManyToOne
@JoinColumn(name = "parent")
private Post parent;
@ManyToOne
@JoinColumn(name = "owner")
private User owner;
或实施自己的NamingStrategy(特定于Hibernate,不推荐给初学者:-))
另外,@ Embrite表示您要将给定实体映射为组件(基本上是同一个表的一部分)。将@ManyToOne和@Embedded放在同一财产上是(或应该)是非法的。