EntityManager.persist() работает в сервлете, но не в отдельном классе

#java #hibernate #jpa

#java #переход в спящий режим #jpa

Вопрос:

Я новичок в JPA и гибернации. Я пытаюсь вставить Thing в мою Thing таблицу в моей базе данных, используя entityManager.persist() . Когда я делаю это внутри сервлета, Thing добавляется, но когда я делаю это из отдельного класса и вызываю метод из сервлета, Thing не добавляется.

Это работает:

 // servlet

@PersistenceContext
EntityManager em;
@Resource
UserTransaction utx;

protected void processRequest(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    try {

        Thing thing = new Thing("word");

        utx.begin();
        em.persist(thing);
        utx.commit();

    } catch (Exception ex) { }

}
  

Но это не:

 // servlet

protected void processRequest(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    Thing thing = new Thing("word");

    ThingDao thingDao = new ThingDao();
    thingDao.add(thing);

}
  

Учитывая,

 // ThingDao

public class ThingDao {

    @PersistenceContext
    EntityManager em;
    @Resource
    UserTransaction utx;

    public void add(Thing thing) {

        try {

            utx.begin();
            em.persist(thing);
            utx.commit();

        } catch (Exception ex) { }

    }

}
  

Почему второй метод не работает? Как мне заставить это работать?

Комментарии:

1. new ThingDao() — создание подобного экземпляра приводит к тому, что контейнер не знает о его существовании, и, следовательно, внедрение не может произойти. Либо позвольте контейнеру внедрить экземпляр в ваш сервлет, либо выполните поиск (конечно, это должен быть вводимый компонент, и вам, вероятно, не нужна зависимая область CDI)

2. Кроме того, вы должны понимать, что catch (Exception ex) { } это очень опасно. Скорее всего, вы получите NullPointerException но поскольку вы даже не регистрируете исключение, вы его никогда не видите и, следовательно, должны задаться вопросом «почему эта вещь не сохраняется» — регистрация исключения должна была привести к тому, что вы поняли, что utx и em в ThingDao равны null, и это соответствующим образом повлияло бы на ваш вопрос. — Удаление: не используйте пустые блоки catch!

3. попробуйте отправить в ThingDao em тоже подобное class ThingDao { public ThingDao(EntityManager em){ this.em=em;} и в ProcessRequest сделайте ThingDao thingDao = new ThingDao(em); thingDao.add(thing);

4. @Dred попробовал то, что вы предложили, не сработало. Однако я изменил add метод внутри ThingDao и вызвал его с помощью thingDao.add(thing, em, utx) , передав EntityManager и UserTransaction при вызове метода, и теперь он добавляет запись просто отлично! Но приходится передавать em и utx в дополнение к thing … Интересно, есть ли другой способ добиться этого без необходимости делать em.persist(thing) внутри самого сервлета.

5. Spring поможет вам с этим или другим DI). Я видел ответ по этому поводу

Ответ №1:

Аннотируйте с помощью @Component и автоматически подключайте его, потому что нет DI.

// ThingDao

 @Compoenent
public class ThingDao {

    @PersistenceContext
    EntityManager em;
    @Resource
    UserTransaction utx;



    public void add(Thing thing) {

        try {

            utx.begin();
            em.persist(thing);
            utx.commit();

        } catch (Exception ex) { }

    }

}
  

//В сервлете

        @Autowired
       ThingDao td;

protected void processRequest(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    Thing thing = new Thing("word");


    td.add(thing);

}
  

Ответ №2:

Изучая код, я предполагаю, что вы используете Spring, если да, то вам не хватает следующего :

  1. класс ThingDao

    @Транзакционный @Общедоступный класс репозитория ThingDao {

  2. serverlet: вам нужно автоматически подключить ThingDao туда

    @Autowired ThingDao td;

Надеюсь, это поможет

Комментарии:

1. На самом деле я заранее не использовал Spring, только Hibernate. Но я добавил библиотеку Spring Framework 4.0.1 в свой проект (в NetBeans) и попробовал то, что вы предложили. Все тот же результат.

2. вы пробовали установить EntityManager em; и UserTransaction utx; из serverlet? т.Е. вам нужно создать setter для em и utx в ThingDao, а затем установить их в serverlet