【问题标题】:Hibernate @One-To-Many similar to @ElementCollectionHibernate @One-To-Many 类似于 @ElementCollection
【发布时间】:2012-06-27 21:08:03
【问题描述】:

我正在尝试做这样的事情,但使用@One-To-Many 而不是@ElementCollection。

public class Book {
    ...
    @ElementCollection
    Set<String> tags;
    ...
}

这会创建两个表,一个用于 Book,另一个用于带有 (BookID, Tag) 的标签,除了我不能将 Criteria 与 @ElementCollection 一起使用这一事实之外,它工作正常。

所以我改变了它并为标签制作了一个包装类:

public class Book {
    ...
    @OneToMany(...)
    Set<BookTag> tags;
    ...
}


public class BookTag {
    ...
    String tag;
    ...
}

问题是使用@OneToMany注解hibernate创建了3张表:一张用于书籍,一张用于标签,一张用于连接书籍和标签。这个解决方案工作得很好,但我想要 2 个表而不是 3 个,因为 Tag 类只包含一个字符串。

有什么方法可以使用 @OneToMany 并让 hibernate 像使用 @ElementCollection 一样创建 2 个表?

【问题讨论】:

  • 您确定不能在条件查询中使用元素集合吗?我们至少有one answer,否则的话。
  • 在我使用 ElementCollection 的情况下,我得到了一个 org.hibernate.MappingException:集合不是关联。然后我读了this 并认为我不能使用 ElementCollection 和 Criteria。
  • 有趣。您可能可以对元素集合执行某些类型的查询,而有些则不能。您要执行什么查询?
  • 我需要列出所有包含某个标签的书。

标签: java hibernate hibernate-mapping


【解决方案1】:

是的,通过指定 OneToMany 必须使用连接列而不是默认值(使用连接表):

@OneToMany(...)
@JoinColumn(name = "BOOK_ID")
private Set<BookTag> tags;

【讨论】:

    【解决方案2】:

    您可以使用 JPA 标准对 @ElementCollection 执行该查询。假设您使用的是元模型,它看起来像这样:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Book> cq = cb.createQuery(Book.class);
    Root<Book> book = cq.from(Book.class);
    
    cq.select(book).where(cb.equal(book.join(Book_.tags), "fanfic"));
    
    TypedQuery<Book> query = em.createQuery(cq);
    

    如果您不使用元模型,则基本相同,但您可能需要使用joinSet

    该查询具有合理的意义。唯一令人惊讶的一点是需要使用join 而不是get,这是因为tags 是复数属性,而不是单数属性,但您正在查看它的各个元素。

    您可能还期望阅读更自然

    cq.select(book).where(cb.isMember("fanfic", book.get(Book_.tags)));
    

    会工作的。也许对于一些 JPA 实现它确实如此。但是对于 Hibernate (4.1.4),它不会;它因语法错误而爆炸。这似乎是Hibernate bug HHH-5209

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-31
      • 1970-01-01
      • 2019-07-26
      • 2018-12-26
      • 2022-12-31
      • 1970-01-01
      相关资源
      最近更新 更多