Hibernate在3层java ee应用程序中延迟加载

时间:2017-07-14 17:49:28

标签: hibernate rest java-ee lazy-loading 3-tier

我已经用hibernate构建了一个Java EE应用程序。我没有使用任何servlet,而是使用用于RESTful WebService的Java API构建的REST API。因为我的模型变得越来越大,我将我的集合从FetchType.EAGER设置为FetchType.LAZY。现在我收到LazyInitializationException消息could not initialize proxy - no Session。我想我确实理解为什么会这样,但我不明白hibernate何时试图访问代理。

实体:

@Entity
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Version
    private Timestamp lastChanged;

    @NotNull
    private Date creationDate;

    @ManyToMany
    private Set<Entity> lazyEntity;

    public User() { }

    // getters and setters
}

DAO:

public interface UserDAO {
    public List<User> getAll();
}

豆:

@Stateless
@Remote(UserDAO.class)
public class UserBean<User> implements UserDAO {

    @PersistenceContext
    protected EntityManager em;

    @Override
    public List<User> getAll() {
        return this.em.createQuery("SELECT u FROM User u ORDER BY u.creationDate", User.class)
                      .getResultList();
    }
}

端点:

@Path("/users")
@Stateless
public class UsersEndpoint {

    @EJB
    private UserDAO userDAO;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAll() {
        List<User> users = userDAO.getAll();
        if (users.size() == 0)
            return Response.status(Response.Status.NOT_FOUND)
                           .build();
        return Response.ok(users).build();
    }
}

我的问题是为什么lazyEntity刚刚返回为null但是引发了错误?在哪个部分是休眠尝试访问lazyEntity,因为正如您在上面的代码中看到的,我不会尝试在API端点内访问。我能赶上例外吗?

如果没有获得异常,我该怎么做才能收到如下对象?我已经看到我可以通过更改属性hibernate.enable_lazy_load_no_trans来禁用它。但我也read强烈建议不要这样做。

User {
    id: 1,
    lastChanged: 0981283812738,
    creationDate: 2178371283098,
    lazyEntity: null
}

1 个答案:

答案 0 :(得分:1)

我认为问题在于getAll()方法的JSON序列化导致UsersEndpoint(由方法上的注释触发)。

我假设您使用Jersey + Jackson(这是一种常见的Java&lt; - &gt; JSON转换器)。

当getAll()方法完成时,Jackson获取方法的结果并尝试通过获取User类的所有数据将其转换为JSON。为此,Jackson在User类中调用getLazyEntity(),并且由于它是延迟加载的,因此触发数据库访问(并且因为会话已关闭而失败)。

如果要在JSON响应中获取“lazyEntity”的数据,则必须在会话关闭之前获取数据:在DAO中使用HQL查询中的获取连接。

如果您不想在JSON中使用lazyEntity,则必须告诉Jackson不要序列化lazyEntity,您可以使用Jackson视图执行此操作。请参阅How can a @JsonView working with jerseyhttp://wiki.fasterxml.com/JacksonJsonViews