Hi,
I'm having an issue when trying to do a Criteria query with FetchMode.JOIN in an lazy load with no-proxy association.
Classes
Code:
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
@Entity
public class Person extends Resident {
private PersonDetail detail;
@LazyToOne(LazyToOneOption.NO_PROXY)
@OneToOne(cascade = CascadeType.ALL, fetch= FetchType.LAZY)
public PersonDetail getDetail() {
return detail;
}
public void setDetail(PersonDetail detail) {
this.detail = detail;
}
/**
*
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{"
+ "id=" + id
+ ", name=" + name
+ ", detail=" + detail
+ '}';
}
}
Code:
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class PersonDetail implements Serializable {
private Long id;
private Person person = new Person();
private Integer age;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "PersonDetail{" + "age=" + age + '}';
}
}
A test class:
Code:
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import testehibernate.models.Person;
public class LazyNoProxyTest {
public static void main(String[] args) {
Session s = HibernateUtil.getSessionFactory().openSession();
//get the House
Criteria c = s.createCriteria(Person.class);
c.setFetchMode("detail", FetchMode.JOIN);
List<Person> p = c.list();
for (Person person : p) {
System.out.println(person.getDetail());
}
}
}
When test run, the sql log out show a query with the appropriate left join:
Code:
Hibernate:
select
this_.id as id1_1_,
this_.detail_id as detail4_1_1_,
this_.name as name1_1_,
persondeta2_.id as id2_0_,
persondeta2_.age as age2_0_
from
Resident this_
left outer join
PersonDetail persondeta2_
on this_.detail_id=persondeta2_.id
where
this_.DTYPE='Person'
But, with you debug, you can see that the detail property wasn't initialized, it remains null.
When the for loop call person.getDetail() the FieldInterceptorImpl do the lazy load, creating a n+1 problem:
Code:
Hibernate:
select
person_.detail_id as detail4_1_
from
Resident person_
where
person_.id=?
I have tested this case both with Hibernate 4.1.2 and 3.6.10, with the same problem.
Anyone facing the same problem?