使用Jackson

时间:2017-05-01 16:29:07

标签: hibernate serialization jackson lazy-loading jboss6.x

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

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

通常情况下,我对此类问题的解决方案是在服务调用期间“预先加载”客户端所需的集合。不幸的是,这只能在交易中完成。当Jackson准备好序列化我的响应时,服务方法已经返回并且事务已经关闭。

有谁知道解决此问题的方法?杰克逊提供了一些可以让我在事务中进行序列化的“钩子”吗?

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

服务提供商 -

@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);
        }
    }
}

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

首先,使用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