mda*_*win 5 java orm hibernate ejb jpa
我试图重构一个旧的应用程序,以使用EJB3和JPA.
我们有两个客户端层(一个基于servlet,一个不是),它们都调用委托层,该层调用EJB层,后者又调用DAO.EJB是EJB2(bean管理的持久性),DAO使用手动SQL查询,提交事务和手动关闭连接.
我想用EJB3替换EJB2,并将所有DAO更改为使用JPA.
我首先使用容器管理的事务用EJB3替换EJB2代码.由于hibernate Criteria非常简单,并且可以注入EntityManager,我可以这样做:
@Stateless
public class NewSelfcareBean implements SelfcareTcApi {
@PersistenceContext(unitName="core")
EntityManager em;
public BasicAccount getAccount(String id) {
Criteria crit = getCriteria(BasicAccount.class);
crit.add(Restrictions.eq("id", id));
BasicAccount acc = (BasicAccount) crit.uniqueResult();
}
}
Run Code Online (Sandbox Code Playgroud)
无需单独的DAO层.帐户对象看起来有点像这样:
@Entity
@Table(name="er_accounts")
public class BasicAccount {
@OneToMany( mappedBy="account", fetch=FetchType.LAZY)
protected List<Subscription> subscriptions;
}
Run Code Online (Sandbox Code Playgroud)
但是在我调用EJB来获取帐户对象的servlet层中,我想构建一个可能(或可能不)包含来自BasicAccount的子订阅的响应:
servlet层看起来像这样:
ResponseBuilder rb;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
Account acc = getDelegateLayer().getAccount();
rb.buildSubscriptionResponse(acc.getSubscriptions());
...
}
Run Code Online (Sandbox Code Playgroud)
显然这不起作用,因为当我们返回到servlet层时,事务和实体管理器已经关闭 - 我得到一个LazyInitializationException.
所以我可以看到一些选择:
Hibernate.init(acc.getSubscriptions())- 这将工作,但需要在EJB中完成.假设我重新使用bean作为另一个不需要订阅的客户端方法?不必要的DB调用.这些选项似乎没有任何好处.
我错过了什么吗?该怎么做?我不能成为第一个遇到这个问题的人......
两个提取策略意味着两个用例,因此在这种情况下您最好编写两个方法:
public BasicAccount getAccount(String id) {
Criteria crit = getCriteria(BasicAccount.class);
crit.add(Restrictions.eq("id", id));
BasicAccount acc = (BasicAccount) crit.uniqueResult();
}
}
public BasicAccount getAccountWithSubscriptions(String id) {
Criteria crit = getCriteria(BasicAccount.class);
crit.add(Restrictions.eq("id", id));
crit.setFetchMode("subscriptions", FetchMode.JOIN);
BasicAccount acc = (BasicAccount) crit.uniqueResult();
}
}
Run Code Online (Sandbox Code Playgroud)
渴望获取通常是代码气味,而服务层(EJB)负责获取数据.发现自己乱砍网络层以添加交易责任是打破应用程序层边界的标志.
更好的方法是使用DTO.JPA实体与持久性相关,它们泄漏数据库和ORM特定的获取检索机制.DTO更适合,因为它可以最小化获取和发送到Web层的数据量,因此是渲染视图的理想选择.虽然您实际上可以在服务层和Web层中使用实体,但是在数据投影是更好的替代方案时存在用例.
| 归档时间: |
|
| 查看次数: |
308 次 |
| 最近记录: |