我正在创建一个 Java EE Web 应用程序,它将使用 JPA 2 EclipseLink 在数据库上运行。我也在使用应用程序管理的实体管理器,所以我可以手动设置事务,尽管我不确定一些事情。
初始信息(仅出于本文的目的,因为有细节/设计部分)我有 JPA 实体:UserEntity 和 UserDetailsEntity 在创建新用户时,我必须创建两个实体的实例,它们链接在一起。
在使用向导从实体类创建 JSF 页面时,我注意到 NetBeans 创建了一个AbstractFacade
和一个实现该外观的企业 Java Bean:UserFacade
和UserDetailsFacade
. 这些 EJB 是 JPA CRUD 操作的基本包装器。
问题:
Facade 模式真的有用吗,尤其是在我想在特定事务中组合几个 JPA 操作的情况下?这种模式对我的设计是好还是坏?为什么?
如果我有“UserManagement 中的事务进程”,事务机制是否会起作用,但不是直接从事务块中执行 .persist,而是执行包装器方法:
utx.begin(); userFacade.create(userEntity); userDetailsFacade.create(userDetailsEntity); utx.commit();
我不确定 EntityManager,我应该有多个实例吗?除了用户身份验证(了解当前登录的用户)之外,我看不到保留一个 EntityManager 实例的理由。我想我可以在每次需要时使用 EntityManagerFactory 来获取实例。但我关心的是这里的性能和好的/坏的设计实践。或者我应该保留一个 EntityManager(在配置类的某个地方获得并通过 Singleton 或 CDI 共享?)
具有类似以下结构的 JSF Pages -> ManagementBean 收集信息并将其相应地传递给正确的 EJB Bean -> EJB bean 将执行业务方法并将信息传递给负责 CRUD 的 Facade EJB -> FacadeEJB 将坚持信息。
AbstractFacade 的代码:(草稿)
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0]);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
UserFacade 的代码(草稿,因为我将修改这个类以从工厂中检索 EntityManagers 而不是使用 CDI):
@Stateless
public class UserEntityFacade extends AbstractFacade<UserEntityEntity> {
@PersistenceContext(unitName = "FMSBetaPU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public TestEntityFacade() {
super(TestEntity.class);
}
}
UserManagement EJB 代码(草稿)
@Stateless
public class UserManagement {
@Resource
private UserTransaction utx;
@EJB
private UserEntityFacade userFacade;
@EJB
private UserDetailsEntityFacade userDetailsFacade;
public void createUser(int id, String name)
{
UserEntity userEntity = new UserEntity(id);
UserDetailsEntity userDetailsEntity = new UserDetailsEntity(name);
try {
utx.begin();
userFacade.create(userEntity);
userDetailsFacade.create(userDetailsEntity);
utx.commit();
}
catch (Exception e) {
try {
utx.rollback();
} catch (IllegalStateException ex) {
Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
} catch (SystemException ex) {
Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}