Tomcat, Hibernate, JPA и Flushing - PullRequest
       2

Tomcat, Hibernate, JPA и Flushing

0 голосов
/ 29 февраля 2012

У меня есть простой проект, который я использую для изучения Hibernate и JPA. У меня есть проект, настроенный и работающий, с возможностью сохранения данных persist () в базе данных (HSQLDB) и возврата данных createQuery ().

Я включил параметр show_sql в persistence.xml, чтобы увидеть, что происходит под ним. Я не понимаю, почему каждый раз, когда я запрашиваю данные, выполняется SQL-запрос, даже если не выполнялась никакая другая транзакция / коммит.

Я использую один EntityManager, созданный с помощью Persistence.createEntityManagerFactory () в методе класса, вызванного моим сервлетом. Когда это создается, я вызываю em.setFlushMode (FlushModeType.COMMIT).

public class ThingPersist {
private static EntityManagerFactory emf;
private static EntityManager em;
public static EntityManager getEntityManager()
{
    if (emf == null)
        emf = Persistence.createEntityManagerFactory("thingPersist");
    if (em == null)
    {   
        em = emf.createEntityManager();
        em.setFlushMode(FlushModeType.COMMIT);
    }
    return em;
}
}

Метод doGet () моего сервлета запрашивает данные (класс Thing имеет переопределения hashCode () и equals ()):

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    EntityManager em = ThingPersist.getEntityManager();
    em.setFlushMode(FlushModeType.COMMIT);
    List<Thing> things = em.createQuery("from Thing", Thing.class).getResultList();
    for (Thing thing : things)
        response.getWriter().println(thing.getSomeString());
}

Hibernate затем показывает следующий SQL:

Hibernate: 
select
    thing0_.id as id0_,
    thing0_.someString as someString0_ 
from
    Thing thing0_

Если я снова вызываю сервлет, выполняется тот же SQL. Если сразу после этого я добавлю другой идентичный блок createQuery (), Hibernate сообщит, что один и тот же SQL-запрос выполняется дважды для каждого doGet ().

Почему Hibernate запрашивает базу данных при каждом вызове? Разве EntityManager не должен кэшировать объект Thing (до тех пор, пока commit () не изменит его)?

Спасибо за любую помощь!

1 Ответ

1 голос
/ 29 февраля 2012

Режим сброса указывает, когда изменения, внесенные в объекты в сеансе, должны быть записаны в базу данных. Это не имеет ничего общего с запросами.

Более того, вы не запускаете транзакцию в своем коде.

И, наконец, даже если вы выполняли запрос, Hibernate выполняет этот запрос. Единственные вызовы, которые не вызывают запрос во второй раз, это em.find() и em.getReference(). Причины в том, что

  • время жизни кэша первого уровня, как правило, очень мало (продолжительность транзакции), и поэтому довольно редко можно выполнить один и тот же запрос дважды в одной транзакции.
  • в зависимости от уровня изоляции, запрос может возвращать разные результаты между двумя вызовами, потому что другая транзакция могла внести изменения между двумя запросами.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...