3 层 java ee 应用程序中的 Hibernate 延迟加载
Hibernate lazy loading within 3-tier java ee application
我已经构建了一个 Java 带有休眠和 wildly 10 的 EE 应用程序。我没有使用任何 servlet,而是使用 Java API 构建的 REST API对于 RESTful Web 服务。因为我的模型变得越来越大,所以我将我的 collections 从 FetchType.EAGER
设置为 FetchType.LAZY
。现在我收到 LazyInitializationException
消息 could not initialize proxy - no Session
。我想我明白为什么会这样,但我不明白休眠何时试图访问代理。
实体:
@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 端点内访问。我能捕捉到异常吗?
我该怎么做才能收到如下 object 而不会出现异常?我已经看到我可以通过更改 属性 hibernate.enable_lazy_load_no_trans
来禁用它。但我也 read 不强烈推荐这样做。
User {
id: 1,
lastChanged: 0981283812738,
creationDate: 2178371283098,
lazyEntity: null
}
我认为问题在于 getAll() 方法的 JSON 序列化导致 UsersEndpoint(由方法上的注释触发)。
我假设你使用 Jersey+Jackson(这是一个常见的 Java<->JSON 转换器)。
当 getAll() 方法完成时,Jackson 获取该方法的结果并尝试通过获取用户 class 的所有数据将其转换为 JSON。为此,Jackson 在用户 class 中调用 getLazyEntity() 并且由于它是延迟加载的,因此触发了数据库访问(并且由于会话关闭而失败)。
如果您想在 JSON 响应中包含 "lazyEntity" 的数据,您必须在会话关闭之前获取数据:在 DAO 内部,在 HQL 查询中使用获取连接.
如果您不想要 JSON 中的 lazyEntity,您必须告诉 Jackson 不要序列化 lazyEntity,您可以使用 Jackson 视图来做到这一点。参见 How can a @JsonView working with jersey and http://wiki.fasterxml.com/JacksonJsonViews。
我已经构建了一个 Java 带有休眠和 wildly 10 的 EE 应用程序。我没有使用任何 servlet,而是使用 Java API 构建的 REST API对于 RESTful Web 服务。因为我的模型变得越来越大,所以我将我的 collections 从 FetchType.EAGER
设置为 FetchType.LAZY
。现在我收到 LazyInitializationException
消息 could not initialize proxy - no Session
。我想我明白为什么会这样,但我不明白休眠何时试图访问代理。
实体:
@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 端点内访问。我能捕捉到异常吗?
我该怎么做才能收到如下 object 而不会出现异常?我已经看到我可以通过更改 属性 hibernate.enable_lazy_load_no_trans
来禁用它。但我也 read 不强烈推荐这样做。
User {
id: 1,
lastChanged: 0981283812738,
creationDate: 2178371283098,
lazyEntity: null
}
我认为问题在于 getAll() 方法的 JSON 序列化导致 UsersEndpoint(由方法上的注释触发)。
我假设你使用 Jersey+Jackson(这是一个常见的 Java<->JSON 转换器)。
当 getAll() 方法完成时,Jackson 获取该方法的结果并尝试通过获取用户 class 的所有数据将其转换为 JSON。为此,Jackson 在用户 class 中调用 getLazyEntity() 并且由于它是延迟加载的,因此触发了数据库访问(并且由于会话关闭而失败)。
如果您想在 JSON 响应中包含 "lazyEntity" 的数据,您必须在会话关闭之前获取数据:在 DAO 内部,在 HQL 查询中使用获取连接.
如果您不想要 JSON 中的 lazyEntity,您必须告诉 Jackson 不要序列化 lazyEntity,您可以使用 Jackson 视图来做到这一点。参见 How can a @JsonView working with jersey and http://wiki.fasterxml.com/JacksonJsonViews。