我正在使用休眠进行持久化。在我的数据访问层中,我根据场景指定了要急切加载的结果的某些部分。
现在我需要将这些结果作为 JAX WS 响应发送。
有什么方法可以让我有一些更简洁的方法,它将获取一个实体对象,遍历它,并设置为未初始化的字段,以便当对象传递到 Web 服务层时null
休眠不会抛出。LazyInitializationException
或者有没有其他方法可以解决这个问题。
有诸如Hibernate#initialize()之类的东西,您可以在加载实体后在活动会话中运行,但它会在您传递的实体(或集合)的根级别初始化字段/引用 - 如果实体是 Hibernate代理人。正如 JavaDoc 所述:
注意:这只确保代理对象或集合的初始化;不能保证集合内的元素将被初始化/物化。
将 NULL 分配给未初始化的字段不是一个好方法,因为它会破坏数据的一致性(如果有人访问这些字段,那么他们应该返回实际值)。
如果您使用的是 Spring,则可以使用 OpenSessionInView(Interceptor|Filter)。这是延迟初始化异常的简单修复,因为它将会话边界与请求边界对齐。我通常不喜欢这种方法,因为它通过对数据库进行额外查询以获取代理数据,从而消除了错误。
在像您这样的情况下,我的偏好是使用具有您对每个呼叫感兴趣的特定字段的传输对象。来回发送不必要的数据是没有意义的,或者更糟的是,发送歪曲持久层实际状态的数据是没有意义的。
我实际上会更进一步,让您的会话边界保持原样,并确保您的 DAO 方法返回的是传输对象而不是实体。人们经常会争辩说实体只是 POJO,这只是更多的工作。但现实情况是,正如您的问题所示,将实体视为 POJO 的尝试可能会导致隐式数据访问,该访问属于专用于数据访问的层。
我在这里有相同的架构,我们在业务层进行加载工作。无法自动执行此操作,因为您只知道 ws 响应中需要哪些数据。基本上,我有一个方法可以将实体模型(JPA 映射)转换为简单的 POJO,反之亦然,在这种方法中我解决了需要加载哪个属性。
你可以使用这样的东西:
public interface IBusiness<Model, VO> {
public Model toModel(VO vo);
public VO toVO(Model model);
public List<Model> toModelList(List<VO> vos);
public List<VO> toVOList(List<Model> models);
}
您在业务层上实现此接口并解决在此方法中加载您需要的所有内容的惰性问题。
祝你好运=)
另一种方法可能是根本不使用延迟初始化。
如何做到这一点取决于您处理的情况。您将在 SO 上找到答案。