2

我目前正在使用以下组件开发分布式应用程序:

1.tier:数据库-服务器-> MySQL 5.5

2.tier:应用服务器-> Glassfish 3.1.2.2

3.tier:独立 Fat-Client -> Java-SE (JRE 6)

我使用 JPA 2.0 (eclipse-link) 作为持久性提供程序,目前使用序列化在第二层和第三层之间传递 @Entity bean。我使用静态编织是为了从 JPA 支持的延迟获取中受益。

我的问题是,由于 2nd/3rd 层之间的序列化延迟获取将不起作用!这会导致大量的网络流量,因为我的一个实体 bean 的每次序列化都要求在通过网络发送之前获取与其他实体/表的所有关系。

在这样的设置中,我如何从 JPA 延迟获取中受益?是否有不需要引入轻量级 DTO/DAO 的解决方法(这会给我的项目增加巨大的复杂性)?

非常感谢您提前提供的帮助!

4

2 回答 2

3

根据我对类似架构的经验,对于一个相当大的项目,DTO 是不可避免的,应该在必要时使用。

使用分离的实体,特别是当它们与其他实体有多个关联时,不仅会由于数据库加载和序列化而导致性能问题,而且还会带来巨大的复杂性。事实上,除非代码有非常好的文档,否则在表示层中很难知道给定的关联是否已加载,这会导致大量延迟初始化异常。

如果您将序列化的分离实体从表示层发送回服务层,情况会更糟,因为这样您最终会得到混合使用分离实体和附加实体的代码,这会使事情变得更加复杂。

因此,我的建议是:

  • 如果实体很简单并且 UI 层不需要太多加载的关联,则将实体从服务层转移到 UI 层。始终记录哪些关联已初始化,哪些未初始化。如果关联过多,请使用 DTO 和即席查询从数据库中加载必要的数据。
  • 当需要大量实体时(例如,返回 O(100) 或更多结果的搜索表单的结果),将 DTO 从服务层转移到 UI 层。使用即席查询加载请求的数据。
  • 避免将实体从表示层转移到服务层。如果这样做,请确保您在服务层中做的第一件事是从数据库重新加载实体的附加版本,或合并接收到的实体,以便始终使用附加实体。调试服务层中抛出的延迟初始化异常并由使用已在几分钟前由前一个屏幕加载的分离实体引起,这不是一件令人愉快的事情。
于 2012-09-22T11:53:54.820 回答
0

我们通过使用负载组和查询提示解决了这个问题,以便定义应该在特定查询中获取的关系的深度。这需要延迟获取,因此在使用 eclipse-link 作为 JPA 提供程序时需要进行编织。

这是一个简短的示例:

特定外观上的服务器端查询:

@Override
public List<Contact> query(LoadGroup group) {
    TypedQuery<Contact> query = em.createQuery("SELECT c FROM Contact c", Contact.class);
    if(group!=null) { query.setHint(QueryHints.LOAD_GROUP, group); }
    return query.getResultList();
}

对该特定外观的客户端查询:

LoadGroup group = new LoadGroup();
group.addAttribute("telephone");
group.addAttribute("address.street");
List<Contact> contacts = remoteContactFacade.query(group);

在此示例中,Contact 表与 Address 和 Telephone 表具有进一步的多对一关系。通过使用点符号,您可以定义应该获取的深度。

希望这可以帮助。

于 2012-10-27T09:52:02.060 回答