JPA; Hibernate 4.3.6; MySQL 6.2 (InnoDB); Веб-приложение Vaadin, работающее на TomcatНовый EntityManager иногда получает устаревшие данные от MySQL
Когда я прочитал сущность из базы данных, я иногда получаю устаревшие данные. Я не могу найти шаблон - иногда один и тот же код извлекает устаревшие данные, затем очищает данные, а затем снова устаревает.
Я получаю новый EntityManager перед каждым запросом. (Я был обеспокоен тем, что я мог бы каким-то образом получить их из пула повторно используемых EntityManager, но сброс «нового» EntityManager дает мне ошибку, что транзакция не выполняется.)
Журнал отладки Hibernate и переход по кода, оба указывают, что каждый раз он ударяет по базе данных.
Все указывает на классическую ошибку: REPEATABLE-READ внутри транзакции, которая ранее считывала (теперь устаревшие) данные. И, конечно же, если я изменю настройку изоляции транзакций MySQL от REPEATABLE-READ до READ-COMMITTED, проблема исчезнет. Но как это возможно, если я каждый раз выделяю новый EntityManager?
Спецификации: Я запустил код ниже и посмотрел правильное значение «OLD» для поля templateFile. Затем я вручную редактирую и фиксирую изменение строки в базе данных, устанавливая ее в «NEW». Когда я запускаю код снова я мог видеть одно из следующих действий:
Filename1: OLD
Filename2: OLD
OR
Filename1: OLD
Filename2: NEW
OR
Filename1: NEW
Filename2: NEW
Какого результата я получаю, как правило, «палку», повторяя каждый раз, когда код работает, по крайней мере, пока я не связываться с другими частями программы. В следующий раз, когда я вернусь к тесту, результаты могут измениться или не измениться.
Код:
// the factory is a static instance, initialized once
EntityManagerFactory myFactory = Persistence.createEntityManagerFactory(“foo.entities.persistence-unit”);
// . . .
// The actual test:
EntityManager entityManager1 = myFactory.getNewEntityManager();
Household household1 = entityManager1.find(Household.class, 7);
entityManager1.refresh(household1);
System.out.println("Filename1: " + household1.getTemplateFile());
// read second copy of same entity
EntityManager entityManager2 = myFactory.getNewEntityManager();
Household household2 = entityManager2.find(Household.class, 7);
entityManager2.refresh(household2);
System.out.println("Filename2: " + household2.getTemplateFile());
persistence.xml:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name=“foo.entities.persistence-unit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/myschema"></property>
<property name="javax.persistence.jdbc.user" value="mydba"></property>
<property name="javax.persistence.jdbc.password" value=“********”></property>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
<property name="javax.persistence.schema-generation.create-database-schemas" value="false"></property>
</properties>
</persistence-unit>
</persistence>
UPDATE: Новый ключ. Проблема также исчезает, когда я переключаюсь с использования источника данных, определенного через свойства, в пул соединений Tomcat. Модуль сохранения теперь выглядит следующим образом:
<persistence-unit name="foo.entities.persistence-unit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/foo</non-jta-data-source>
</persistence-unit>
Каковы ваши границы транзакций? – Rohit
Цель состоит в том, чтобы транзакции выполнялись приложением. (Мы не используем EJB, который, я считаю, исключает возможность управления транзакциями контейнером в любом случае.) Отсюда мое предположение о том, что новая EntityManger == новая транзакция ... Если есть код или файл конфигурации, которые окончательно ответят на ваш вопрос , дайте мне знать, что вам показать ... может быть, это и есть наша проблема. – Bampfer
FYI Я добавил обновление: проблема, кажется, исчезает, когда я получаю пул соединений Tomcat вместо определения источника данных через свойства в файле persistence.xml. Но я до сих пор не знаю, что с этим делать. – Bampfer