Hibernate не сбрасывает измененные объекты в базу данных - PullRequest
1 голос
/ 07 апреля 2011

Я работаю над проектом, который за последние пару месяцев разработал невероятно раздражающую ошибку, связанную с обновлениями объектов. Некоторые объекты (особенно пользователи) при обновлении в спящем режиме никогда не помечаются как грязные и очищенные. Например:

Session session = factory.openSession(interceptor);
Transaction tx = session.beginTransaction();

Object object = session.load(someId);
// Modify object ...
session.update(object);

tx.commit();

session.flush();
session.close();

Все соответствующие методы на перехватчике вызываются hibernate, кроме Interceptor.onFlushDirty и Interceptor.findDirty. Мое первоначальное предположение заключалось в том, что это была проблема с отсоединенными объектами, поскольку мы хранили объект пользователя в сеансе http; однако рефакторинг, который удалил все отсоединенные объекты, не решил проблему.

Транзакция определенно фиксируется, и по завершении сеанс сбрасывается и закрывается. Я также дважды проверил, чтобы сеанс не был доступен только для чтения.

Я также пытался использовать Session.merge вместо Session.update безрезультатно. При использовании Session.merge возвращаемый объект содержит правильную обновленную информацию, но, опять же, база данных никогда не обновляется.

Я нашел этот ТАК вопрос, который, кажется, описывает аналогичную проблему (уместно, потому что объект, над которым я работаю, хранит пользовательское поле enum) и хорошее описание механизма грязной проверки Hibernate но кроме этой информации было немного скудно.

Мой cfg.xml выглядит так:

<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.default_batch_fetch_size">1024</property>
<property name="hibernate.order_inserts">true</property>
<property name="hibernate.order_updates">true</property>
<property name="hibernate.show_sql">false</property>

<property name="hibernate.c3p0.aquire_increment">1</property>
<property name="hibernate.c3p0.initial_pool_size">1</property>
<property name="hibernate.c3p0.min_size">4</property>
<property name="hibernate.c3p0.max_size">32</property>
<property name="hibernate.c3p0.idle_test_period">100</property> <!-- seconds -->
<property name="hibernate.c3p0.timeout">600</property> <!-- seconds -->

<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</property>

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

<property name="hibernate.jdbc.fetch_size">1024</property>

<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

<property name="hibernate.search.worker.execution">async</property>
<property name="hibernate.search.default.directory_provider">org.hibernate.search.store.RAMDirectoryProvider</property>
<property name="hibernate.search.default.indexwriter.batch.ram_buffer_size">256</property>
<property name="hibernate.search.default.optimizer.transaction_limit.max">1000</property>

ОБНОВЛЕНИЕ: Я пытался как отключить, так и включить кэш второго уровня Hibernates, так как Finbarr предложил безрезультатно.

У кого-нибудь есть предложения по поводу других вещей, которые я мог бы попробовать?

Ответы [ 4 ]

0 голосов
/ 14 сентября 2015

Проблема в коде: вы совершаете транзакцию перед сбросом сеанса!Вы должны очистить сеанс, который будет «синхронизировать» состояние сеанса с текущей транзакцией, а затем зафиксировать транзакцию:

Session session = factory.openSession(interceptor);
Transaction tx = session.beginTransaction();

Object object = session.load(someId);
// Modify object ...
session.update(object);
session.flush();

tx.commit();
session.close();
0 голосов
/ 19 апреля 2011

Finbarr было частично правильно, это почти наверняка проблема кеширования, но не кеш второго уровня. принудительно заставляет Hibernate выполнять обновление независимо от того, изменилось ли оно, теперь все сохраняется правильно.

session.evict(object);
session.update(object);
0 голосов
/ 27 июля 2012

В контексте моего проекта я наткнулся на кусок кода, который сделал именно то, что вы упомянули выше: evict затем обновите.Дополнительные элементы в ваших расследованиях пролили больше понимания по этому вопросу.Ошибка или нет, в конце концов, вы сообщили об этом поведении / ошибке в спящий режим и / или у вас есть ссылка на этот JIRA?Какая у вас была версия hibernate?

По потенциальной причине: -1 - вы упомянули сеанс только для чтения, но не только для чтения на уровне запроса или уровне объекта -2 - вы проверили, что объект не был выселениз сеанса (EvictEventListener) -3- вы проверили, что объект больше не изменяется в исходное состояние, следовательно, не требует обновления или повторного вызова обновления с более старой (отсоединенной) версией объекта

Любой вклад приветствуется, С уважением, Кристоф

0 голосов
/ 07 апреля 2011

Попробуйте отключить кэш второго уровня hibernate.На самом деле, вы можете опубликовать свой cfg.xml?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...