As an example if you have an entity Author
public class Author {
private long id;
private String name;
private Set books = new HashSet();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getBooks() {
return books;
}
public void setBooks(Set books) {
this.books = books;
}
public long getId() {
return id;
}
void setId(long id) {
this.id = id;
}
public void addBook(Book b){
books.add(b);
}
}
with his mapping file Author.hbm.xml :
<hibernate-mapping package="org.dreborier.domain"> <class name="Author" table="AUTHOR"> <id name="id" column="AUTHOR_ID"> <generator class="native"></generator> </id> <property name="name" column="NAME"></property> <set name="books" table="BOOK" cascade="save-update" fetch="join"> <key column="AUTHOR_ID"></key> <one-to-many class="Book"/> </set> </class> </hibernate-mapping>
and the entity Book :
public class Book {
private long id;
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getId() {
return id;
}
void setId(long id) {
this.id = id;
}
}
along with the mapping file Book.hbm.xml :
<hibernate-mapping package="org.dreborier.domain">
<class name="Book" table="BOOK">
<id name="id" column="BOOK_ID">
<generator class="native"></generator>
</id> <property name="title" column="TITLE"></property> </class>
</hibernate-mapping>
<class name="Book" table="BOOK">
<id name="id" column="BOOK_ID">
<generator class="native"></generator>
</id> <property name="title" column="TITLE"></property> </class>
</hibernate-mapping>
if you use a query by Criteria :
Criteria criteria = session.createCriteria(Author.class);
List authors = criteria.list();
List
with the fecth="join" attribute hibernate will execute the following query :
select this_.AUTHOR_ID as AUTHOR1_0_1_, this_.NAME as NAME0_1_, books2_.BOOK_ID as BOOK1_0_3_, books2_.BOOK_ID as BOOK1_3_, books2_.BOOK_ID as BOOK1_1_0_, books2_.TITLE as TITLE1_0_ from AUTHOR this_ left outer join BOOK books2_ on this_.AUTHOR_ID=books2_.BOOK_ID
so books are loaded along with authors.
while if you use HQL :
Query query = session.createQuery("from Author");
List authors = query.list();
List
hibernate will execute the following query:
select author0_.AUTHOR_ID as AUTHOR1_0_, author0_.NAME as NAME0_ from AUTHOR author0_
as you can see the fetch="join" do not affect the HQL query and a second query wiil be executed when an author's book is accessed
so if you want to fetch eagerly the Book using HQL you have to use left join fetch :
Query query = session.createQuery("from Author as author left join fetch author.books");
Hibernate Reference Documentation recommends
The following code:
select author0_.AUTHOR_ID as AUTHOR1_0_0_, author0_.NAME as NAME0_0_ from AUTHOR author0_ where author0_.AUTHOR_ID=?
and
select books0_.AUTHOR_ID as AUTHOR3_0_1_, books0_.BOOK_ID as BOOK1_1_, books0_.BOOK_ID as BOOK1_1_0_, books0_.TITLE as TITLE1_0_ from BOOK books0_ where books0_.AUTHOR_ID=?
while with fetch="join" the database is hit only one time
select author0_.AUTHOR_ID as AUTHOR1_0_1_, author0_.NAME as NAME0_1_, books1_.AUTHOR_ID as AUTHOR3_0_3_, books1_.BOOK_ID as BOOK1_3_, books1_.BOOK_ID as BOOK1_1_0_, books1_.TITLE as TITLE1_0_ from AUTHOR author0_ left outer join BOOK books1_ on author0_.AUTHOR_ID=books1_.AUTHOR_ID where author0_.AUTHOR_ID=?
as you can see the fetch="join" do not affect the HQL query and a second query wiil be executed when an author's book is accessed
so if you want to fetch eagerly the Book using HQL you have to use left join fetch :
Query query = session.createQuery("from Author as author left join fetch author.books");
Hibernate Reference Documentation recommends
Usually, the mapping document is not used to customize fetching. Instead, we keep the defaultbehavior, and override it for a particular transaction, using left join fetch in HQL. This tellsHibernate to fetch the association eagerly in the first select, using an outer join. In the Criteriaquery API, you would use setFetchMode(FetchMode.JOIN).The fetch="join" attibute defined in the mapping file affects get and load methods.
The following code:
Author author = (Author) session.get(Author.class, 1L);
Set books = author.getBooks();
books.size();
without the fetch attribute will produce two database hitsselect author0_.AUTHOR_ID as AUTHOR1_0_0_, author0_.NAME as NAME0_0_ from AUTHOR author0_ where author0_.AUTHOR_ID=?
and
select books0_.AUTHOR_ID as AUTHOR3_0_1_, books0_.BOOK_ID as BOOK1_1_, books0_.BOOK_ID as BOOK1_1_0_, books0_.TITLE as TITLE1_0_ from BOOK books0_ where books0_.AUTHOR_ID=?
while with fetch="join" the database is hit only one time
select author0_.AUTHOR_ID as AUTHOR1_0_1_, author0_.NAME as NAME0_1_, books1_.AUTHOR_ID as AUTHOR3_0_3_, books1_.BOOK_ID as BOOK1_3_, books1_.BOOK_ID as BOOK1_1_0_, books1_.TITLE as TITLE1_0_ from AUTHOR author0_ left outer join BOOK books1_ on author0_.AUTHOR_ID=books1_.AUTHOR_ID where author0_.AUTHOR_ID=?
Nessun commento:
Posta un commento