Hibernate @ One-To-Many类似于@ElementCollection

时间:2012-06-27 21:08:04

标签: java hibernate hibernate-mapping

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

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

这创建了两个表,一个用于Book,另一个用于带有(BookID,Tag)的Tags,它工作正常,除了我不能将条件与@ElementCollection一起使用。

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

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


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

问题是使用@OneToMany注释hibernate创建了3个表:一个用于书籍,一个用于标签,一个用于连接书籍和标签。这个解决方案很完美,但是我希望有2个表而不是3个,因为Tag类只包含一个String。

有没有办法使用@OneToMany并让hibernate像@ElementCollection一样创建2个表?

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

您可以使用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