开发者

Netbeans generates different JPA code in "JPA Controllers from enetity beans" and "JSF pages from entity beans"

There are two different JPA code generator wizards in Netbeans while using JPA entity beans in a Java EE and web project.

The first wizard generates "JPA Controllers from enetity beans". The second wizard generates "JSF pages from entity beans", which creates facade classes that do pretty much the same things as the controllers from the first wizard, but with alternate coding. What is the difference between the facade classes and the JPA controllers?

Here's how the generated code from the first wizard look like:

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

}

And here's from the second wizard:

 @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().getCriteriaBuilde开发者_开发问答r().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();
    }

}

This is a matter of design. Which is better? I prefer using the second wizard and implement Facade only for revealing the functionality of the JPA controllers. Is that the 'right' way from design perspective? Now, if they are so identical in meaning, why does the JPA controller contain so much coding?


I don't use Netbeans, so I won't speak for it directly, I'm merely diagnosing the generated code.

The "JPA Controllers from enetity beans" generates Java SE compatible DAO-like classes. There is no means of container managed dependency injection anywhere. The entity manager is manually created and the transactions are manually managed. Those classes will work just fine in both a "plain vanilla" Java SE desktop application and in a Java EE web application.

The "JSF pages from entity beans" generates Java EE compatible DAO-like classes in flavor of a stateless EJB. The entity manager is injected by the container and the transactions are fully transparently managed by the container (by specification, a single stateless EJB method call counts as a single full transaction). They require a Java EE container to be run on and they can't be used in a Java SE desktop application. As the Java EE container transparently manages the dependency injection and transactions, this explains why they have much less code.

The "JPA Controller" can thus also just be used as-is in a Java EE web application, but you may run into transactional problems sooner or later. Imagine that a single HTTP request (a single web form submit) is intented to execute multiple DB actions through multiple of those classes in a certain sequence and that everything should be rolled back whenever one of the latter actions fails with an exception. This would not work when you're using the "JPA Controller" approach without refactoring a lot of code so that the transactions are been created externally, but this would work fully transparently the way you'd expect when using the EJBs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜