Hibernate @SelectBeforeUpdate (false) не работает, если без сгенерированного hibernate значения @Id - PullRequest
0 голосов
/ 25 марта 2019

Я обнаружил, что если сопоставление сущностей без спящего генерирует значение первичного ключа, SelectBeforeUpdate(false) не будет работать.

@Entity
@SelectBeforeUpdate(false)
class X {
    protected X(){}
    @Id
    @GeneratedValue
    UUID id;

    int x;
}

Если закомментировать @GeneratedValue, назначить значение идентификатора в X ctor, @SelectBeforeUpdate(false) потеряет свою функциональность.

Из-за гибернации будет проверяться, является ли отсоединенный объект временным или нет ForeignKeys.isTransient в org\hibernate\engine\internal\ForeignKeys.java, что в конечном итоге вызывает IdentifierValue.isUnsaved в org\hibernate\engine\spi\IdentifierValue.java. Без @GeneratedValue hibernate использует статический UNDEFINED экземпляр класса IdentifierValue, который isUnsaved метод всегда возвращает null. Это вызовет ForeignKeys.isTransient return null, так что hibernate наконец создаст моментальный снимок, который вызовет SQL выбора.

Однако проблема в том, что @GeneratedValue разделяет конструкцию объекта на 2 фазы: сначала новый, а затем передайте его в session.save. Мне это не нравится, есть ли обходной путь, чтобы @SelectBeforeUpdate(false) работал без того, чтобы hibernate генерировал значение @Id? Я использую UUID, чтобы быть ПК, поэтому нет необходимости позволять Hibernate сделать это.

Я использую Hibernate 5

1 Ответ

0 голосов
/ 26 марта 2019

Наконец-то я разобрался с этим механизмом.Для hibernate поле @Id обрабатывается в унифицированной процедуре любого типа: если вы хотите, чтобы hibernate сгенерировал для вас значение id, вы должны вызвать session.save, даже значение id может быть определено на этапе создания объекта.

Это проблематично: если пользователь использует UUID в качестве первичного ключа, это означает, что пользователь хочет определить значение до связи с базой данных.Для некоторой сложной логики, после создания объекта A, объект A должен выполнить некоторые дополнительные действия, после этого объект A должен вместе с другим объектом B в транзакции совершить транзакцию в базу данных.Если идентификатор объекта А равен нулю до фиксации базы данных, это очень неудобно из-за того, что объект еще не является законченным объектом.

Hibernate использует процедуру генерации унифицированного идентификатора в качестве предположения, которое используется для определения объекта, является временным илине.Если @GeneratedValue это add, hibernate считает объект временным, только если значение id равно нулю (это довольно просто, если значение id не равно нулю, тогда необходимо вызвать session.save).Если без генератора hibernate не может знать этот факт, единственный способ выяснить это - выбрать его из базы данных.Поэтому необходимо пропустить @SelectBeforeUpdate (false)

. Единственный способ изменить процедуру - это самостоятельно определить Interceptor, который переопределяет Interceptor.isTransient, однако для этого требуется, чтобы пользователь реализовал проверку переходных процессов.Если в нем всегда возвращается false, сохранение и обновление должны вызываться точно.

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