如何通过hibernate最好地处理关联表/外键?

时间:2012-01-18 06:44:42

标签: sql hibernate persistence

我使用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是一种可能的替代方案,还是应该避免将关联表放在一起?这个问题的解决方案是什么?

2 个答案:

答案 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表中的其他列,你需要它。但就像我说的那样,明天我将不得不挖掘片段。