Отключить автоматическое обновление Hibernate при сбросе на синонимах только для чтения - PullRequest
4 голосов
/ 29 июня 2009

У меня есть таблица и две базы данных, которые имеют одну и ту же таблицу, но одна является символической ссылкой другой, и в этой таблице разрешено только чтение.

Я сопоставил таблицу с Java с помощью Hibernate и использую Spring, чтобы установить источник данных Entity Manager в качестве одной из двух баз данных на основе некоторых критериев ввода.

Я вызываю только операции «только чтение» (выбирает), когда я подключен ко второй базе данных, но, похоже, Hibernate пытается что-то сбросить обратно в базу данных, и он не может сказать, что обновление в этом представлении запрещено.

Как отключить это обновление только для второго источника данных и сохранить его нормальным для первого?

Обновление: Глядя на трассировку стека, здесь, кажется, начинается сброс:


          at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
          at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
          at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
          at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
          at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:504)
          ... 55 more

Это связано со свойством hibernate.transaction.flush_before_completion? Могу ли я установить значение false для второго источника данных?

Ответы [ 2 ]

7 голосов
/ 29 июня 2009

Скорее всего, ваши сущности становятся "грязными" в тот момент, когда они загружаются из базы данных, и Hibernate считает, что необходимо сохранить изменения. Это происходит, если ваши методы доступа (методы get и set) не возвращают точно такое же значение или ссылку , которые были установлены Hibernate.

В нашем коде это произошло со списками, разработчики создали новые экземпляры списков, потому что им не понравился тип, который они получили в установщике.

Если вы не хотите менять код, измените отображение на доступ к полю.

Вы также можете предотвратить сохранение изменений в Hibernate, установив для параметра FlushMode значение никогда не включаться в сеанс, но это только скрывает реальную проблему, которая все еще будет возникать в других ситуациях и приведет к ненужным обновлениям.

1 голос
/ 29 июня 2009

Сначала вам необходимо определить, является ли это DDL или DML. Если вы не знаете, то я рекомендую установить hibernate.show_sql = true , чтобы зафиксировать ошибочное утверждение.

Если это DDL, то, скорее всего, Hibernate обновит схему для вас, и вы захотите дополнительно настроить параметр hibernate.hbm2ddl.auto , чтобы либо " update ", либо " none ", в зависимости от того, используете ли вы фактическую базу данных или символическую ссылку (только для чтения), соответственно. Вы также можете использовать " validate " вместо none.

Если это DML, то я бы сначала определил, вносит ли ваш код по какой-то причине изменения в экземпляр, который все еще присоединен к активной сессии Hibernate. Если это так, то последующее чтение может вызвать сброс этих изменений без явного сохранения объекта (Grails?). Если это так, рассмотрите возможность удаления экземпляра, вызывающего сброс (или использования вместо этого транспортных объектов).

Возможно, вы используете какие-либо аспекты или события жизненного цикла Hibernate для обеспечения аудита объектов? Это также может привести к доступу только для чтения, что приведет к запуску вставки или обновления.

Может оказаться, что вам нужно предоставить альтернативные сопоставления классу-нарушителю, если в игру вступает возможность обновления поля, но код делает все именно так, как вы хотите (это маловероятно; 0). Если вы находитесь в мире аннотаций, это может быть сложно. Если вы работаете с hbm.xml, то обеспечить альтернативное сопоставление проще.

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