使用 Jackson 序列化 Hibernate Bean

Serializing Hibernate Beans With Jackson

我正在为项目创建一些现有服务的 RESTful 版本。当前应用程序将 Hibernate 3 与 jboss 6 服务器一起使用,因此我添加的任何新服务都必须在该环境中运行。我决定从一个简单的 GET 请求开始。我设法正确设置了所有内容,我的服务方法是 运行。我 运行 遇到的问题是,当 Jackson 尝试序列化响应以将其发送回客户端时,我得到 'lazy load' 异常。

我看到的针对此问题的两种最常见的解决方案在这里都行不通。将获取类型更改为 EAGER 可能会破坏我现有的服务。添加注释以忽略导致异常的字段也不起作用,因为客户端需要这些字段。

通常,我对此类问题的解决方案是 'front-load' 客户在服务调用期间需要的集合。不幸的是,这只能在事务中完成。当 Jackson 准备好序列化我的响应时,服务方法已经返回并且事务已经关闭。

有谁知道解决此问题的方法吗? jackson 是否提供了一些 'hook' 可以让我在交易中进行序列化?

更新 这是我的代码的示例:

服务提供商-

@Path("service")
public interface ClientServiceProvider
{
    @GET
    @Path("web/brand/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public abstract Response getBrandWeb(@PathParam("id") Long brandId);
}

服务bean-

@Stateless(name = "ClientServiceProvider")
@Local(ClientServiceProvider.class)
public class ClientServiceProviderBean implements ClientServiceProvider
{
    @Override
    public Response getBrandWeb(Long brandId)
    {
        try
        {
            Functions.beginTx(tx);

            Brand b = entityManager.find(Brand.class, brandId);
            if (!b.getSubCollections().isEmpty())
            {
                b.getSubCollections().size();
            }
            Response r = null;
            if (b != null)
            {
                r = Response.ok(b).build();
            }
            else
            {
                r = Response.serverError().build();
            }
            Functions.commitTx(tx);
            return r;
        }
        catch (Exception e)
        {
            return quietRollback(tx, e, Response.class);
        }
    }
}

最灵活的解决方案是使用在事务上下文中创建的DTOs

使用 DTO,您可以根据使用结果 JSON 的客户端的确切需求定制要序列化的对象。此外,域模型(Hibernate 实体)与 JSON(反)序列化逻辑分离,允许两者独立发展。

首先,使用DTO是最好的解决方案。我不喜欢 DTO,但在这种情况下它会很有帮助。因为,您不仅需要实现 GET 端点,还需要实现 POST/PUT 端点。

此外,如果您将 Swagger 与实体一起使用,您将在 Swagger 文档中拥有所有 Hibernate 支持属性(如双向关联)。

您可以使用 Dozer 或您自己的映射器来减少 DTO 映射错误的数量。在这种情况下,我实现了自己的简单映射器(没有浅拷贝,并为集合和其他复杂情况提供了额外的自定义方法)。

此外,使用 DTO 映射器,您可以自动获取需要序列化的延迟属性 — 映射器将尝试复制这些属性并触发延迟获取。

所以,如果您不想使用 DTO

,您可以做什么
  1. 在打开会话(在事务内)时获取您需要的所有关联。
  2. 使用 jackson-datatype-hibernate 模块调整 Jackson 以不序列化未获取的关联,如下所述: Avoid Jackson serialization on non fetched lazy objects