Нужна помощь со структурой дизайна и поиском EntityManager и UserTransaction в помощнике помощника

Я в основном новичок, начинающий работу над новым веб-приложением. Веб-приложение — это в основном ваши основные операции CRUD. Для этого я решил использовать JPA с Hibernate в качестве поставщика Persistence и буду разрабатывать на Apache Derby для целей разработки и тестирования. Я использую GlassFish v2 в качестве сервера приложений для развертывания своих компонентов EJB3. Для внешнего интерфейса я использую JSF (Visual JSF с темой Woodstock, которая поставляется в комплекте с NeatBeans v6.5)

Вот так я и поступал до сих пор. Я использую мастера NetBeans 6.5 по большей части для создания своих классов сущностей и сеансовых компонентов ejb. Что я делаю, так это создаю новую таблицу в Apache Derby, скажем, XXX. Затем я использую «Классы сущностей из базы данных» для создания класса сущностей XXX, который содержит все необходимые аннотации и методы получения и установки.

Затем я запускаю мастер «Класс контроллера 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(){}

Затем я запускаю мастер «Session Beans for Entity Classes», чтобы сгенерировать локальные/удаленные сеансовые компоненты EntityFacade, которые при необходимости могут быть вызваны внешним интерфейсом следующим образом:

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

Поскольку у меня уже есть сгенерированные классы Controller, которые реализуют эти методы с лучшей поддержкой 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 или есть лучший способ сделать это? Я ввожу здесь какую-то избыточность? Это шаблон, которому я в значительной степени следовал для всех классов Entity: создать класс сущности -> создать класс контроллера -> создать класс entityfacade -> изменить класс entityfacade для вызова методов класса контроллера.

PS: я использую JTA

Это, в свою очередь, привело меня к другой проблеме. Все сгенерированные классы контроллеров имеют свои собственные методы getEntityManager(). Поэтому, чтобы избавиться от этой избыточности, я решил использовать вспомогательный класс по аналогии с HibernateUtil.java, который обычно встречается в руководствах по Hibernate (который действует как синглтон для sessionfactory). Поэтому я создал PersistenceUtil.java с методами getEntityManager() и getUserTransaction(), которые должны возвращать экземпляры EntityManager и UserTransaction для использования классами контроллера.

Вот где проблема. Я использую @PersistenceContext ((name="jpa/EntityManager") и @Resource (name="jta/UserTransaction") в классах XXXFacade. Таким образом, я могу получить доступ к записям JNDI для em и utx как из класса XXXFacade ( если мне нужно, хотя в моем случае я этого не делаю) и в вспомогательном классе XXXJpaController (через поиск jndi). Прочитав в Интернете, вот что я узнал. Вспомогательные классы должны использовать поиск JNDI в среде компонента bean ( java:comp/env), так как инъекция выполняется только для управляемых контейнером bean-компонентов, а не для неуправляемых вспомогательных классов. Это отлично работает для класса Controller, экземпляр которого создается в классе XXXFacade, как показано в приведенном выше коде. Однако я не могу использовать PersistenceUtil для поиска либо EntityManager, либо UserTransaction, поскольку я предполагаю, что это вспомогательный класс помощника. Что я могу сделать, чтобы обойти это и получить доступ к управляемому контейнером entitymanager и usertransaction в вспомогательном классе PersistenceUtil? Один из вариантов, который приходит мне на ум, также создать экземпляр класса Persistence в каждом классе XXXFacade (мне не нравится, как это звучит).

Единственный другой вариант, который я могу придумать, — это избавиться от класса Controller и переместить весь этот код в класс XXXFacade. Таким образом, мне даже не понадобится вспомогательный класс PersistenceUtil, поскольку я смогу напрямую внедрить его в сессионный компонент, верно?

Как я уже говорил в начале, я новичок. Я хочу услышать от всех вас, опытных и опытных ветеранов java/jee, совета по этому вопросу. Есть ли какой-то конкретный шаблон, который я могу использовать здесь?

Мне жаль, если что-то из этого не имеет для вас смысла. Пожалуйста, не стесняйтесь обращаться ко мне за любыми разъяснениями, и я буду более чем счастлив сделать это.


person SibzTer    schedule 28.04.2009    source источник


Ответы (2)


Одна вещь, которую вы, возможно, захотите изучить, — это Spring для управления вашими транзакциями, а не с использованием фабричного метода.

У вас здесь много всего, просто в качестве совета: я обнаружил, что чем легче усваивается вопрос, тем лучше ответы вы получаете не только в Stack Overflow, но и в Интернете в целом. Я понимаю, что при столкновении с множеством новых технологий может быть сложно сформировать четкие вопросы, в моей собственной истории вопросов есть несколько гигантских вопросов, но важно прояснить свои мысли и проблемы, прежде чем просить кого-то еще помочь вам с ними. Возможно, вы захотите поработать над тем, чтобы разбить это на несколько вопросов, сосредоточившись на четкой постановке одного вопроса. Как правило, людям будет легче помочь вам, если вы заранее потратите время на то, чтобы задать четкий вопрос.

person James McMahon    schedule 29.04.2009

Да.. вы абсолютно правы. Прошу прощения за формат вопроса. На самом деле это была моя самая первая публикация в stackoverflow и, следовательно, уродство вопроса. В любом случае, благодаря вашим отзывам я попытался опубликовать более качественные вопросы.

В любом случае, я нашел ответы на свои вопросы. Я решил не использовать классы контроллера и просто использовать сеансовые фасадные компоненты для сущностей. И я использовал постоянство, управляемое контейнером. Так что больше нет необходимости в методах getEntityManager() или вспомогательных классах. Вместо этого используйте DI формы "@PersistenceContext". Кроме того, поскольку я использую постоянство, управляемое контейнером, мне больше не нужны пользовательские транзакции.

person SibzTer    schedule 21.08.2009