我使用schemaExport来创建像这样的表
Configuration config = new Configuration();
config.addAnnotatedClass(Categories.class);
config.addAnnotatedClass(Article.class);
config.configure();
new SchemaExport(config).create(true, true);
Categories.java和Article.java的重要部分是:
Article.java
@Id
@GeneratedValue
public Long getId() {
return id;
}
@OneToMany( cascade = CascadeType.ALL )
public Set<Categories> getCategories() {
return categories;
}
Categories.java
@Id
@GeneratedValue
public Long getId() {
return id;
}
@ManyToOne(cascade = CascadeType.ALL)
public Article getArticleCategories() {
return articleCategories;
}
运行时,Schema Export会生成三个表:Article,Categories和article_categories。 article_categories是一个关联表,其中两个主键与Article和Categories中的键匹配。在我的ApplicationContext.xml中只有ArticleFactory添加了Article和Categories,因为我生成时显然没有第三个表作为类。我写了这个HQL:
"from Article a, article_categories ac, Categories c where ac.Article_id = a.id and ac.categories_id = c.id and c.category = 'p'"
Hibernate无法运行它,因为未映射article_categories。我需要映射吗?运行本机SQL而不是HQL是一种可能的替代方案,还是应该避免将关联表放在一起?这个问题的解决方案是什么?
答案 0 :(得分:2)
HQL不适用于表。它适用于实体及其关联。在HQL查询中创建实体之间的连接,Hibernate将使用连接表为您生成适当的SQL。
示例:
select a from Article a
inner join a.categories c
where c.category = :categoryName
阅读(至少)the HQL section of the reference manual。
旁注:实体的名称应该是单数:类别而不是类别。因此,一篇文章有Set<Category>
,名为categories
。更容易阅读和理解这种方式。类别的category
字段应命名为name
:它是类别的名称,而不是其类别。
答案 1 :(得分:1)
不太确定,如果原始数据库或导出中有错误。我们使用相同的方法,但之后重构表格。 (我会尝试找到我们使用的脚本,如果你需要它并明天再回来)
在任何情况下:如果没有除外键之外的其他字段,则不需要m:n关系的实体类:
在类别中:
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "article_categories",
joinColumns = { @JoinColumn(name = "article_id", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "category_id", nullable = false, updatable = false) })
private Set<Article> articles;
文章:
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "article_categories",
joinColumns = { @JoinColumn(name = "category_id", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "article_id", nullable = false, updatable = false) })
private Set<Category> categories;
这将创建m:n表。
当我们运行hibernate导出器时,实际上我们得到了一个映射类和一个键类,如果你想要m:n表中的其他列,你需要它。但就像我说的那样,明天我将不得不挖掘片段。