【问题标题】:Netbeans generates different JPA code in "JPA Controllers from enetity beans" and "JSF pages from entity beans"Netbeans 在“来自实体 bean 的 JPA 控制器”和“来自实体 bean 的 JSF 页面”中生成不同的 JPA 代码
【发布时间】:2011-10-02 16:04:02
【问题描述】:

在 Java EE 和 Web 项目中使用 JPA 实体 bean 时,Netbeans 中有两个不同的 JPA 代码生成器向导。

第一个向导生成“从 enetity bean 生成 JPA 控制器”。第二个向导生成“来自实体 bean 的 JSF 页面”,它创建的外观类与第一个向导中的控制器所做的事情几乎相同,但使用了不同的编码。外观类和 JPA 控制器有什么区别?

第一个向导生成的代码如下所示:

 public class UserimagesJpaController {

    public UserimagesJpaController() {
        emf = Persistence.createEntityManagerFactory("ArticlesWeb-ejbPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Userimages userimages) throws PreexistingEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Users users = userimages.getUsers();
            if (users != null) {
                users = em.getReference(users.getClass(), users.getIdUsers());
                userimages.setUsers(users);
            }
            em.persist(userimages);
            if (users != null) {
                users.getUserimagesList().add(userimages);
                users = em.merge(users);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findUserimages(userimages.getIdUserImages()) != null) {
                throw new PreexistingEntityException("Userimages " + userimages + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Userimages userimages) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Userimages persistentUserimages = em.find(Userimages.class, userimages.getIdUserImages());
            Users usersOld = persistentUserimages.getUsers();
            Users usersNew = userimages.getUsers();
            if (usersNew != null) {
                usersNew = em.getReference(usersNew.getClass(), usersNew.getIdUsers());
                userimages.setUsers(usersNew);
            }
            userimages = em.merge(userimages);
            if (usersOld != null && !usersOld.equals(usersNew)) {
                usersOld.getUserimagesList().remove(userimages);
                usersOld = em.merge(usersOld);
            }
            if (usersNew != null && !usersNew.equals(usersOld)) {
                usersNew.getUserimagesList().add(userimages);
                usersNew = em.merge(usersNew);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = userimages.getIdUserImages();
                if (findUserimages(id) == null) {
                    throw new NonexistentEntityException("The userimages with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Userimages userimages;
            try {
                userimages = em.getReference(Userimages.class, id);
                userimages.getIdUserImages();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The userimages with id " + id + " no longer exists.", enfe);
            }
            Users users = userimages.getUsers();
            if (users != null) {
                users.getUserimagesList().remove(userimages);
                users = em.merge(users);
            }
            em.remove(userimages);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Userimages> findUserimagesEntities() {
        return findUserimagesEntities(true, -1, -1);
    }

    public List<Userimages> findUserimagesEntities(int maxResults, int firstResult) {
        return findUserimagesEntities(false, maxResults, firstResult);
    }

    private List<Userimages> findUserimagesEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Userimages.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Userimages findUserimages(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Userimages.class, id);
        } finally {
            em.close();
        }
    }

    public int getUserimagesCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Userimages> rt = cq.from(Userimages.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}

这是来自第二个向导:

 @Stateless
 public class UserimagesFacade extends AbstractFacade<Userimages> {
    @PersistenceContext(unitName = "ArticlesWeb-ejbPU")
    private EntityManager em;

    protected EntityManager getEntityManager() {
        return em;
    }

    public UserimagesFacade() {
        super(Userimages.class);
    }

 }

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();
    }

}

这是设计问题。哪个更好?我更喜欢使用第二个向导并实现 Facade 只是为了显示 JPA 控制器的功能。从设计的角度来看,这是“正确”的方式吗?现在,如果它们的含义如此相同,为什么 JPA 控制器包含这么多代码?

【问题讨论】:

    标签: jakarta-ee jsf-2 netbeans-6.9


    【解决方案1】:

    我不使用Netbeans,所以我不会直接说,我只是诊断生成的代码。

    “来自 enetity bean 的 JPA 控制器”生成与 Java SE 兼容的类似 DAO 的类。任何地方都没有容器管理的依赖注入的方法。实体管理器是手动创建的,事务是手动管理的。这些类在“普通”Java SE 桌面应用程序和 Java EE Web 应用程序中都可以正常工作。

    “来自实体 bean 的 JSF 页面”以无状态 EJB 的风格生成与 Java EE 兼容的类似 DAO 的类。实体管理器由容器注入,事务由容器完全透明地管理(根据规范,单个无状态 EJB 方法调用算作单个完整事务)。它们需要在 Java EE 容器上运行,并且不能在 Java SE 桌面应用程序中使用。由于 Java EE 容器透明地管理依赖注入和事务,这就解释了为什么它们的代码要少得多。

    “JPA 控制器”因此也可以在 Java EE Web 应用程序中按原样使用,但您迟早会遇到事务问题。想象一下,单个 HTTP 请求(单个 Web 表单提交)旨在通过多个这些类以特定顺序执行多个 DB 操作,并且每当后面的操作之一失败时 everything 都应该回滚有一个例外。当您使用“JPA 控制器”方法而不重构大量代码以便在外部创建事务时,这是行不通的,但这将完全透明地工作,就像您在使用 EJB 时所期望的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-10
      • 2019-07-13
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      相关资源
      最近更新 更多