Netbeans генерирует другой код JPA в «контроллерах JPA из bean-компонентов enetity» и «страницах JSF из bean-компонентов entity» - PullRequest
3 голосов
/ 11 июля 2011

Существует два разных мастера создания кода JPA в Netbeans при использовании бинов сущностей JPA в Java EE и веб-проекте.

Первый мастер генерирует «Контроллеры JPA из bean-компонентов enetity». Второй мастер генерирует «страницы 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 содержит так много кодирования?

1 Ответ

7 голосов
/ 04 июля 2012

Я не использую NetBeans, поэтому я не буду говорить об этом напрямую, я просто диагностирую сгенерированный код.

"Контроллеры JPA из bean-компонентов enetity" генерируют Java SE-совместимый DAO-подобныйклассы.Средств внедрения зависимостей, управляемых контейнером, нет нигде.Менеджер сущностей создается вручную, а транзакции управляются вручную.Эти классы будут отлично работать как в обычном настольном приложении Java SE, так и в веб-приложении Java EE.

"Страницы JSF из компонентов управления данными" генерируют DAO-подобные классы, совместимые с Java EE, в духеEJB без гражданства.Менеджер сущностей внедряется контейнером, и транзакции полностью прозрачно управляются контейнером (по спецификации, один вызов метода EJB без сохранения состояния считается как одна полная транзакция).Для них требуется контейнер Java EE, и они не могут использоваться в настольном приложении Java SE.Поскольку контейнер Java EE прозрачно управляет внедрением зависимостей и транзакциями, это объясняет, почему у них гораздо меньше кода.

Таким образом, «Контроллер JPA» также можно просто использовать как есть в веб-приложении Java EE, ноВы можете столкнуться с транзакционными проблемами рано или поздно.Представьте себе, что один HTTP-запрос (одна отправка веб-формы) предназначен для выполнения нескольких действий с БД через несколько этих классов в определенной последовательности и что all следует откатывать всякий раз, когда одно из последних действий завершается неудачно сисключение.Это не сработает, когда вы используете подход «JPA Controller» без рефакторинга большого количества кода, чтобы транзакции создавались извне, но это будет работать полностью прозрачно, как вы ожидаете при использовании EJB.

...