Без реальных тестов, которые вы выполняли, способа, которым вы их выполняли, и результатов, которые вы получили (от слушателя), трудно сказать что-нибудь умное, однако используя MySQL со следующей таблицей и данными
CREATE TABLE `test` (
`id` int(11)
`data` char(1),
PRIMARY KEY (`id`)
);
+----+------+
| id | data |
+----+------+
| 1 | a |
+----+------+
Я провел этот тест
EntityManagerFactory emf = ...
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
// persisting new item
Test b = new Test();
b.id = 2;
b.data = 'b';
tx.begin();
em.persist(b);
tx.commit();
// update existing item
b.data = 'a';
tx.begin();
em.merge(b);
tx.commit();
// load existing
Test a = em.find(Test.class, 1);
// remove existing
tx.begin();
em.remove(b);
tx.commit();
em.close();
emf.close();
и получил следующий вывод
prePersist(2: b)
postPersist(2: b)
preUpdate(2: a)
postUpdate(2: a)
postLoad(1: a)
preRemove(2: a)
postRemove(2: a)
(я реализовал toString()
в Test
, чтобы он выдавал id + ": " + data
, и я сократил количество записей в моем классе прослушивателя до System.out.format("preXxx(%s)\n", e)
, чтобы его было лучше читать.)
Пожалуйста, посмотрите, работает ли этот в вашей среде для начинающих, чтобы мы могли сузить проблему, но, по крайней мере, опубликовать некоторые из ваших входов / выходов.
Я пытался загрузить простое тестовое приложение JBoss / Seam для себя, чтобы запустить тест, однако я не получаю Seam & hellip; совсем. Во всяком случае, я посмотрел на ваши примеры, и вот что я думаю, что ваша проблема.
Испытание 1 / Ouput 1
Я предполагаю, что ваш runTest()
метод запускает управляемый сеанс персистентности или что-то в этом роде, поэтому перед вызовом метода entityManager.getTransaction().begin()
вызывается Seam, а когда метод существует, вызывается entityManager.getTransaction().commit()
. Вот мое мнение о том, что, кажется, происходит в вашем сценарии.
// transaction begin
// persist - @PrePersist called
this.entityManager.persist(e);
// flush - @PostPersist should be called
this.entityManager.flush();
// clear - the context is cleared
this.entityManager.clear();
// transaction end
Я тестировал этот сценарий, однако использование MySQL с ручным управлением сохранением @PostPersist
называется.
Я пытался установить entityManager.setFlushMode(...)
на FlushModeType.AUTO
и FlushModeType.COMMIT
, но это ничего не меняет. Однако в документации Seam есть третье перечисление, FlushModeType.MANUAL
, которое не входит в спецификацию JPA и является специфичным для Seam. Он должен быть подан к аннотации @Begin
(эта аннотация, вероятно, указывает, что аннотированный метод запускает транзакцию под рукой).
Я совершенно уверен, что в вашем случае flush()
ничего не фиксирует в базе данных, пока транзакция не завершится (методы запускают out ). Если вы удалите вызов метода clear()
, будет вызван @PostPersist
.
Тест 2 / Выход 2
Мне кажется, это нормально!
Тест 3 / Выход 3
Полагаю, ваша проблема в том, что @PrePersist
и @PostPersist
вообще не вызывают, но вы звоните persist()
. Поскольку вы используете find()
, возвращенные экземпляры уже будут управляться. Вызов persist()
на них ничего не делает. Однако изменение их состояния и вызов flush()
вызывает @PreUpdate
. @PostUpdate
не вызывается по той же причине @PostPersist
не вызывается в первом тесте: вы очищаете контекст постоянства, прежде чем что-либо может распространиться в базу данных.
Заключение
Ваша проблема сводится к тому, что вы clear()
сохраняете свой контекст постоянства, прежде чем что-либо будет зафиксировано в базе данных.
Я предлагаю вам сделать действительно простых тестов и попробовать поиграть с настройками FlushModeType
, которые я упомянул. Обновите свою версию Hibernate. Я использую последнюю версию из серии 3.x.x (3.8.6.Final). Кстати, вы точно не поделились с нами своей версией Hibernate, но это может иметь большое значение!