я пытался наблюдать за поведением прокси-сервера JPA2/Hibernate4 ниже,
// Круговая сущность с ленивой загрузкой:
@Entity
public class Employee {
@Id@Generated
int id;
String name;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
Employee boss;
public String toString() {
return id + "|" + name + "|" + boss;
}
//getters and setters ...
}
// Сохраняемые сущности:
// Outer entity:
Employee employee = new Employee();
employee.setName("engineer");
// Inner entity:
Employee boss = new Employee();
boss.setName("manager");
employee.setBoss(boss);
entityTransaction.begin();
entityManager.persist(employee);
entityTransaction.commit();
System.out.println(employee);
// Выход:
Hibernate: insert into Employee (id, boss_id, name) values (default, ?, ?)
Hibernate: insert into Employee (id, boss_id, name) values (default, ?, ?)
2|engineer|1|manager|null
// Загружаем внешний объект:
String queryString = "select e from Employee e where e.id=" + employee.getId();
Query query = entityManager.createQuery(queryString);
Object loadedEmployee = query.getSingleResult();
System.out.println(loadedEmployee.getClass().getSimpleName());
// Выход:
Hibernate: select employee0_.id as id2_, employee0_.boss_id as boss3_2_, employee0_.name as name2_ from Employee employee0_ where employee0_.id=2 limit ?
Employee
К моему удивлению, загруженный внешний объект выше все еще обычный, но я ожидал, что он будет Hibernate proxy
в результате lazy loading
. Я мог что-то пропустить здесь, так как это сделать правильно? Простой, но конкретный пример приветствуется!
@РЕДАКТИРОВАТЬ
Согласно ответу от @kostja
, я адаптировал код и отладил его в режиме SE ниже, ни LazyInitializationException
не удалось создать, ни boss property
проксировать. Любые дополнительные подсказки?
@ИЗМЕНИТЬ 2
Наконец, я бы подтвердил, что ответ от @kostja
, несомненно, великолепен.
Я тестировал в режиме EE, поэтому proxied boss property
наблюдался ниже,
// LazyInitializationException
брошено:
public Employee retrieve(int id) {
Employee employee = entityManager.find(Employee.class, id);
// access to the proxied boss property outside of persistence/transaction ctx
Employee boss = employee.getBoss();
System.out.println(boss instanceof HibernateProxy);
System.out.println(boss.getClass().getSimpleName());
return boss;
}
// Зеленый свет после установки Spring Tx
на место:
@Transactional
public Employee retrieve(int id) ...
// Выход:
true
Employee_$$_javassist_0
Также можно обратиться к 20.1.4. Инициализация коллекций и прокси из документов Hibernate.