我使用的是JEE6堆栈,包括JPA 2.0,JSF 2.0,EJB 3.1等。
我的架构设置方式如下:
我使用hibernate作为JPA提供程序,使用JPA注释DAO。 我有JSF托管bean,它对应于我的facelet / xhtml页面。 我有处理所有数据库请求的EJB。
我的XHTML页面有JSF EL,可以调用我的Managed bean。我的托管bean包含对由EJB管理的DAO实体的引用。例如,我有一个映射到db表的用户实体。我有一个用户EJB,它处理所有返回用户的CRUD操作。我有一个编辑用户的页面。高级工作流程将是:导航到用户编辑页面 - > EL调用位于托管bean中的方法来加载用户。该方法从EJB调用userEJB.loadUser(user)以从数据库中获取用户。用户已编辑并提交 - >在托管bean中调用一个函数,该函数调用EJB中的函数来保存用户。等
我遇到了使用EJB访问我的JSF页面中的数据的问题。 我在延迟初始化错误方面遇到了很多问题,我认为这是由于我已经设置好了。
例如,我有一个Client实体,它有一个懒惰加载的用户列表。为了得到 我在EJB中调用一个方法来访问数据库,找到一个客户端并返回它。稍后的 我希望访问此客户端用户列表,为了这样做,我必须通过调用某种方法返回到EJB以加载这些用户(因为它们被延迟加载)。这意味着我必须创建一个方法,如
public List<User> getUserListByClient(Client c)
{
c = em.merge(c); return c.getUserList();
}
这种方法的唯一目的是加载用户(我甚至不肯定这种方法是好的还是有效的)。 如果我自己正在进行会话管理,我想让会话打开整个请求并直接访问属性,这样会很好,因为会话无论如何都会打开,似乎在EJB中有一个额外的间接层这对我来说很难。
我喜欢EJB,因为我喜欢它们由容器控制,汇集,免费提供事务管理等等。但是,我觉得我使用它们不正确,或者我已经设置了我的JSF应用程序不正确。
非常感谢任何反馈。
感谢,
答案 0 :(得分:2)
如果我正在进行会话管理 我自己,我想离开 会话打开整个请求 并直接访问该属性,这 会议将是好的 无论如何打开
实际上,这是open session in view模式(在视图中也称为开放的EntityManager)。它也可以与EJB一起使用。理想情况下,应该在业务层/ EJB中管理事务,因此可以看出这与纯层体系结构略有不同。但它解决了视图中延迟加载的问题,并且很容易。
否则,您必须确保急切地加载事务结束后将使用的信息。或者你可能依赖DTO,但后来开始变得很麻烦。
以下是另外两个涵盖该主题并讨论优缺点和替代方案的链接:
答案 1 :(得分:1)
你的用法似乎很好。请记住,em.merge(c)可能会将对客户端c所做的更改保存到数据库中。如果您只想获取客户端c的UserList而不保存对客户端c所做的更改,那么您可以这样做:
public List<User> getUserListByClient(Client c)
{
Client client = em.find(Client.class, c.clientId);
return client.getUserList();
}
或者更好的是,只需将客户端ID发送到getUserListByClient,而不是传递一个完整的Client对象,只是为了节省一点点内存:)