我基本上是一个新手,他开始开发一个新的 webapp。webapp 主要是您的基本 CRUD 操作。为此,我决定使用 JPA 和 Hibernate 作为持久性提供程序,并将在 Apache Derby 上进行开发以用于开发和测试目的。我使用 GlassFish v2 作为 App Server 来部署我的 EJB3 bean。对于前端,我使用的是 JSF(带有 Woodstock 主题的 Visual JSF,与 NeatBeans v6.5 捆绑在一起)
所以这就是我到目前为止的工作方式。我大部分时间都在使用 NetBeans 6.5 向导来生成我的实体类和 ejb 会话 bean。我所做的是,我在 Apache Derby 中创建一个新表,例如 XXX。然后我使用“来自数据库的实体类”来生成 XXX 实体类,其中包含所有必要的注释以及 getter 和 setter 方法。
接下来,我运行“来自实体类的 JPA 控制器类”向导来生成控制器类代码 XXXJpaController,它基本上包含以下内容:
@Resource private UserTransaction utx = null;
@PersistenceUnit(unitName = "TestEnterpriseApplication-ejbPU") private EntityManagerFactory emf = null;
1. EntityManager getEntityManager() { return emf.createEntityManager() }
2. void create(XXX xxx) throws PreexistingEntityException, RollbackFailureException, Exception{}
3. void edit(XXX xxx) throws NonexistentEntityException, RollbackFailureException, Exception{}
4. void destroy(Long id) throws NonexistentEntityException, RollbackFailureException, Exception {}
5. List<XXX> findXXXEntities(){}
6. List<XXX> findXXXEntities(int maxResults, int firstResult) {}
7. List<XXX> findXXXEntities(boolean all, int maxResults, int firstResult){}
8. XXX findXXX(Long id){}
9. int getXXXCount(){}
然后,我运行“实体类的会话 Bean”向导来生成 EntityFacade 本地/远程会话 bean,这些 bean 可以在需要时由前端调用,如下所示:
@PersistenceContext private EntityManager em;
1. void create(XXX xxx) { em.persist(xxx); }
2. void edit(XXX xxx) { em.merge(xxx); }
3. void remove(XXX xxx) { em.remove(em.merge(xxx)); }
4. List<XXX> findAll() { return em.createQuery("select object(o) from XXX as o").getResultList(); }
由于我已经有了实现这些方法的生成控制器类,更好地支持 try、catch 和事务,我决定在 XXXFacade.java 中调用它,如下所示:
XXXJpaController XXXController = new XXXJpaController();
1. public void create(XXX xxx) throws PreexistingEntityException, RollbackFailureException, Exception {
XXXController.create(xxx); }
2. public void edit(XXX xxx) throws NonexistentEntityException, RollbackFailureException, Exception{
XXXController.edit(xxx); }
3. public void remove(XXX xxx) throws NonexistentEntityException, RollbackFailureException, Exception{
XXXController.destroy(xxx.getId()); }
4. public XXX find(Object id) {
return XXXController.findXXX((Long)id); }
5. public List<XXX> findAll() {
return XXXController.findXXXEntities(); }
所以这是我的第一个问题。这是在 JEE 世界中做事的正确方法还是有更好的方法?我在这里引入某种冗余吗?这是我对所有实体类几乎都遵循的模式:创建实体类 -> 创建控制器类 -> 创建实体外观类 -> 更改实体外观类以调用控制器类方法
ps:我用的是JTA
这反过来又把我引向了另一个问题。所有生成的控制器类都有自己的 getEntityManager() 方法。因此,为了摆脱这种冗余,我决定使用 Hibernate 教程中常见的 HibernateUtil.java 的辅助类(它充当 sessionfactory 的单例)。所以我创建了一个 PersistenceUtil.java,它有 getEntityManager() 和 getUserTransaction() 方法,它们应该返回控制器类使用的 EntityManager 和 UserTransaction 的实例。
这就是问题所在。我在 XXXFacade 类上使用 @PersistenceContext ((name="jpa/EntityManager") 和 @Resource (name="jta/UserTransaction")。所以我可以从 XXXFacade 类(如果我必须这样做,但在我的情况下我没有)和 XXXJpaController 帮助器类(通过 jndi 查找)。在线阅读后,这就是我发现的。帮助类需要在 bean 的组件环境上使用 JNDI 查找( java:comp/env),因为注入只针对容器管理的 bean 而不是非托管的辅助类。这对于在 XXXFacade 类中实例化的 Controller 类来说很好,如上面的代码所示。但是,我无法使用 PersistenceUtil 类来查找 EntityManager 或 UserTransaction,因为我猜测它是一个助手的助手类。我可以做些什么来解决这个问题并访问 PersistenceUtil 帮助程序类中的容器管理 entitymanager 和 usertransaction?我想到的一个选择是也在每个 XXXFacade 类中实例化 Persistence 类(我不喜欢那样的声音)。
我能想到的唯一其他选择是摆脱 Controller 类并将所有代码移动到 XXXFacade 类中。这样我什至不再需要 PersistenceUtil 辅助类,因为我可以直接将它注入会话 bean,对吗?
就像我一开始提到的,我是新手。我希望听到所有经验丰富且经验丰富的 java/jee 退伍军人在此问题上的指导。我可以在这里使用任何特定的模式吗?
如果这对你没有任何意义,我很抱歉。请随时向我询问任何澄清,我将非常乐意这样做。