我有两个实体,书和作者。
@Entity
@Table(name="book")
class Book {
private int id;
private Map<Integer, Author> authors = new HashMap<Integer, Author>();
@Id
@GeneratedValue
@Column(name="id_book")
public int getId() {
return this.id;
}
@OneToMany(fetch=FetchType.EAGER)
@JoinTable(name="book_author", joinColumns= {@JoinColumn(name="id_book")},
inverseJoinColumns = {@JoinColumn(name="id_author", table="author")})
@MapKeyColumn(name="order")
public Map<Integer, Author> getAuthors() {
return authors;
}
}
@Entity
@Table(name="author")
class Author {
private int id;
private String lastname;
private String firstname;
@Id
@Column(name="id_author")
@GeneratedValue
public int getId() {
return id;
}
public String getLastname() {
return lastname;
}
public String getFirstname() {
return firstname;
}
}
一本书有许多作者按特定顺序列出。现在我正在尝试创建一个HQL,以便我可以从特定作者获得具有特定名字或姓氏或两者的书籍列表。我对如何在两个实体之间使用连接感到困惑。有什么想法吗?
提前致谢。
答案 0 :(得分:4)
第一:书与作者之间存在一对多的关系。一本书可以有很多作者,但是一位作者只能写一本书。如果一个真实的人写了很多书,那么他需要表格作者中的许多行,每本书需要一行。这可能不是你想要的,但你已经定义了这样的关系。
一对多关系在数据库端工作,表作者的书名为id。通过在getBookID()
中创建getter Author
,在Java中提供此ID。然后您可以使用HQL语句
from Book b inner join Author a
where b.id = a.bookId
and a.lastname = :ln
and a.firstname = :fn
或
from Book b where b.id in (select bookId from Author a
where a.lastname = :ln
and a.firstname = :fn)
第二:现在你可能更喜欢一个作者可以有很多书。然后你有一个多对多的关系。为此,建议引入包含多对多关系的交叉表。此交叉表仅包含两列,即书籍ID和作者ID,书籍和作者都具有一对多的关系(并且作者不再拥有bookId)。 HQL语句与第一种情况类似,只是它们超过三个表。
编辑:使用您的Book_Author表格: 对于您的选择,您必须创建一个类BookAuthor,它映射到该表。 然后您可以使用HQL语句
from Book b inner join BookAuthor ba inner join Author a
where b.id = ba.bookId
and ba.authorId = a.id
and a.lastname = :ln
and a.firstname = :fn
或
from Book b where b.id in (select ba.bookId from BookAuthor ba, Author a
where ba.authorId = a.id
and a.lastname = :ln
and a.firstname = :fn)