Java EE Entity Session Bean最佳实践:retrieveAfromB方法应归属何处?
Java EE 实体会话Bean开发规范与问题解答
方法存放方案选型结论
你描述的场景为基于A的实体实例,查询与之关联的B实体,选择第二种方案(将方法放在A对应的实体会话Bean中)更符合Java EE规范,理由如下:
- 实体会话Bean的核心设计原则是与所管理的实体绑定,所有以该实体为入参起点、或者返回该实体为核心结果的操作,都归属到对应会话Bean下。你的需求以A的实例为查询起点,调用上下文属于A的操作场景,因此归到A的会话Bean更合理。
- 如果放在B的会话Bean中,会导致B的会话Bean不必要地依赖A的实体定义,提升组件耦合度,后续如果A实体的关联字段调整,还要修改B的会话Bean逻辑,不符合单一职责原则。
补充:如果是基于B的实例查询关联的A,方法才应该放在B的会话Bean中。如果双向查询场景都存在,允许两个会话Bean各自提供对应方向的查询方法,无需强行合并。
实体会话Bean的职责边界
通常所说的实体会话Bean,指的是Java EE中封装单实体CRUD及关联业务操作的@Stateless无状态会话Bean,职责边界遵循以下规则:
- 仅负责管理自身绑定的实体类的持久化操作,包括单实体的增删改查、基于该实体属性的过滤查询、该实体与其他实体的关联查询(以自身实体为查询入口)
- 不负责处理其他实体本身的业务逻辑,比如操作B实体属性的更新逻辑,绝对不能出现在A的会话Bean中
- 不对外暴露直接的持久化上下文,所有对实体的操作都要经过会话Bean的方法封装,避免上层业务直接操作
EntityManager导致逻辑散落 - 跨实体的复杂业务流程(比如同时修改A和B的关联属性且需要事务保证一致性的操作),应该放到上层的业务门面会话Bean中,不要在实体会话Bean中实现跨实体的事务逻辑
相关开发最佳实践
- 实体类中的getter/setter仅负责实体属性的读写,不要在其中加入持久化逻辑,关联属性的懒加载触发要统一放到会话Bean的方法中处理,避免上层业务调用时出现懒加载异常
- 实体会话Bean建议统一继承通用CRUD父类,减少重复代码,比如封装
findById()、persist()、merge()、remove()等通用方法 - 关联查询的方法要明确指定fetch策略,避免不必要的N+1查询问题,涉及懒加载的关联属性,要在会话Bean方法中确认完成初始化再返回,避免上层调用时持久化上下文已关闭
- 所有对外暴露的方法都要声明事务属性,默认使用
REQUIRED即可,只读查询可以指定SUPPORTS提升性能
内容的提问来源于stack exchange,提问作者Ziyue
相关产品推荐
相关产品推荐

