MyObject myObject = repositoryHibernateImpl.getMyObjectFromDatabase();
//transaction is finished, and no, there is not an option to reopen it
ThirdPartyUtility.doStuffWithMyObjectType( myObject );
此时你已经定义了什么是懒惰和急切加载,第三方实用程序将尝试调用你的“myObject”实例上的所有方法,这很好,因为你不想返回任何东西对于延迟加载的属性,不幸的是它不返回null,它会抛出LazyInitializationException
。
这是因为您实际上是在Hibernate的对象代理上调用该方法,并且它知道它没有获取该数据,并抛出异常。
甚至可以使用null值获取底层对象,以便getter只返回null,并且不会抛出异常?基本上分离对象,以便Hibernate完全不再了解它。延迟加载的对象的访问器必须返回null,它不能返回实际值,我们希望能够将实体转换为POJO,而不必创建看起来像实体的对象,并且必须重新映射所有值。
答案 0 :(得分:2)
让我们说你有一个领域,你可以在吸气器中:
MyField getMyField() {
if (Hibernate.isInitialized(myField)) {
return myField;
}
return null;
}
来自org.hibernate.Hibernate的javadoc:
public static boolean isInitialized(对象代理):检查是否 代理或持久集合是 初始化。
答案 1 :(得分:0)
如果您不想将域与Hibernate耦合,另一种可能性是让您的DAO从getMyObjectFromDatabase()内部实例化您自己的实体实例,并使用Hibernate代理中的相应字段填充该实例。我做到了这一点,效果很好。
显然,这是更多的代码,但如果你想要的话,你可以保证你的实体的“纯粹”实例(包含null未初始化的值)。
答案 2 :(得分:0)
检查我的解决方案。
最小例子:
我不从对象加载属性,而是从控制器加载属性 代码:
{..}
MyProp prop = employeeController.getMyProp(employee);
{..}
这将通过存储库对象初始化该属性并将其返回 EmployeeController.java:
public Set<MyProp> getMyProp(Employee employee) {
if (this.employeeRepository.InitMyProp(employee)){
return employee.getMyProp();
}
return null;
}
存储库获取/打开会话,重新加载员工对象!并初始化延迟加载的字段
EmployeeRepository.java:
public boolean InitMyProp(Employee employee) {
if (Hibernate.isInitialized(employee.getMyProp())){
return true;
}
try {
Session session = getSession();
session.refresh(employee);
Hibernate.initialize(employee.getMyProp());
} catch (Exception ex) {
return false;
}
return true;
}
private Session getSession(){
if (session == null || !session.isConnected() || !session.isOpen()){
session = HibernateUtil.getSessionFactory().getCurrentSession();
}
if (!session.getTransaction().isActive()) {
session.beginTransaction();
}
return session;
}
我在我的解决方案中有一个包含数千条记录的TableView和另外两个TableView,其中包含第一个TableView中所选记录的详细信息。
希望它有所帮助。