Я использую PreInsertEventListener
Hibernate для аудита полей моей таблицы.Я также использую Spring для создания своих SessionFactory и TransactionManager.
Некоторые другие подробности, которые могут иметь отношение:
Используется OpenSessionInViewFilter
Версия Hibernate: 3.5.1-Final
Версия Spring: 3.0.3.RELEASE
База данных Oracle 10g
Использование сеанса в событии небезопасно, поскольку он, вероятно, сбрасывается, поэтому я создаю новый сеанс.
public boolean onPreInsert(final PreInsertEvent event) {
final SessionFactory factory = triggeringSession.getSessionFactory();
Session triggeringSession = event.getSession();
triggeringSession.doWork(new Work() {
public void execute(Connection connection) throws SQLException {
Session newSession = factory.openSession(connection);
saveStuff(newSession);
newSession.flush();
}
});
return false;
}
В моемsaveStuff
метод Мне нужно сохранить новую сущность.
private void saveStuff(Session session) {
HistoricReference historicReference = new HistoricReference();
historicReference.setId("12345"); // This is actually an unique ID based on a generated auditing number and table that was inserted into
// If this haven't been created I want it to be saved
if (session.get(HistoricReference.class, "12345") == null) {
session.save(historicReference);
}
// Other stuff saved (regarding old/new values etc.) that historicReference as id (as part of composite id)
}
Моя проблема в том, что если я вставлю 2 новых сущности одного типа в одну транзакцию, я получу уникальное нарушение ограничения в таблице HistoricReference.Я отлаживал, и код, который проверяет, создан ли он уже, всегда возвращает false, но в конце, когда транзакция фиксируется, он пытается вставить ее дважды.Это потому, что каждый раз создается новый сеанс?
Пример:
MyEntity entity1 = new MyEntity();
MyEntity entity2 = new MyEntity();
session.save(entity1);
session.save(entity2);
Я получу уникальную ошибку ограничения в конце запроса (при попытке зафиксировать).Это потому, что когда onPreInsert(...)
вызывается для entity2, он снова вызывает session.save(historicReference)
.Если я не сохраню entity2, проблем не возникнет.
Будет ли session.get(HistoricReference.class, "12345")
возвращать значение, даже если оно было сохранено в другом сеансе, но в той же незафиксированной транзакции?
У меня есть обходной путь для этой проблемы, но он немного хакерский (логическое значение, привязанное к транзакции, использующей TransactionSynchronizationManager
, чтобы предотвратить сохранение исторической ссылки дважды) и предпочел бы более чистое решение (или, по крайней мере, лучшее пониманиепочему он не работает так, как я ожидаю).
Любая помощь будет оценена.