Каково значение владения недвижимостью и как CASCADE работает с обеими сторонами в JPA?

У меня две таблицы. Сделки и ошибки. Между транзакциями и ошибками существует связь «один ко многим». Это двунаправленная связь, и Errors является стороной-владельцем, поскольку @JoinColumn указывается в классе Errors. Я хочу понять, что именно означает «СОБСТВЕННЫЕ» отношения. Скажи, что сейчас у меня есть

  • ОБРАБОТАНО (столбец в ТРАНЗАКЦИЯХ) установлено на N
  • АКТИВНЫЙ (столбец в ОШИБКАХ) установлен на 1

Сценарий 1: Теперь предположим, что мы выполняем приведенный ниже код.

transactions.setProcessed("Y");
errors.setActive(0);
transactions.setErrors(errors);
entityManager.merge(transactions);

Я понимаю, что поле ОБРАБОТАНО будет установлено на "Y" в ТРАНЗАКЦИЯХ, но будет ли поле АКТИВНО в ОШИБКАх также установлено на 0 или не будет, учитывая, что транзакции НЕ ЯВЛЯЮТСЯ стороной отношения ВЛАДЕНИЕ?

Сценарий 2: С другой стороны, если мы выполним следующее:

errors.setActive(0);
transactions.setProcessed("Y");
errors.setTransactions(transactions);
entityManager.merge(errors);

Я понимаю, что АКТИВНОЕ поле, указанное в ОШИБКАх, будет иметь значение 0, но будет ли поле ОБРАБОТАНО в ТРАНЗАКЦИЯХ также быть установлено на «Y», учитывая, что ОШИБКИ ЯВЛЯЮТСЯ СОБСТВЕННОЙ стороной отношения?

Как каскадные типы JPA связаны с подобными сценариями?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
46
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Теперь переходит ко второй части вашего вопроса, касающейся обновления транзакций и ошибок. На мой взгляд, вы можете обновить список, связанный с транзакцией, применив соответствующий каскадный режим (сохранение, удаление и т. д.), Что означает, что вы можете указать в своей транзакции сущность @OneToMany(cascade=CASCADETYPE.MERGE), указав при этом обратную связь. Таким образом, если вы будете обновлять строку транзакции, соответствующие строки ошибок также могут быть обновлены.

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

спасибо за объяснение и вклад. Однако в моем случае я вынужден позволить дочернему элементу (Ошибкам) ​​обновлять родительский элемент (Транзакции). Поскольку после устранения / уведомления об ошибке мне нужно установить флаг (Processed = Y) в таблице TRANSACTIONS. Я мог бы сделать это, получив объект Transaction, а затем вызвав для него отдельную операцию слияния, но тогда это был бы дополнительный вызов. Как вы думаете, мне следует сделать 2 вызова для слияния, один для обновления ОШИБОК и один для обновления ТРАНЗАКЦИЙ?

worldbeater 01.09.2018 00:29

В не двунаправленных отношениях вы определяете отображение. Когда вы вносите изменения в это сопоставление, очевидно, что произойдет - внешний ключ обновится. Поскольку существует только одно сопоставление, конфликта быть не может (многие провайдеры JPA выдают ошибки, если обнаруживают, что у вас есть более одного доступного для записи сопоставления для поля).

При двунаправленной связи этот контроль менее очевиден. Предположим, что в двунаправленной связи «транзакция-ошибка» это двунаправленное сопоставление OneToOne, а для параметра Transaction1 установлено значение Error1 и наоборот. Допустим, ваше приложение определяет, что Transaction1 следует указывать на Error2, и изменяет ссылку. Если ссылка Error1 на Transaction1 не исправлена, чтобы отразить эту ситуацию, существует проблема для JPA в определении того, какое значение следует поместить во внешний ключ. Вот где в игру вступает владение. Сторона-владелец считается записываемым отображением, и его изменения управляют полями внешнего ключа. В OneToMany стороной-владельцем обычно является обратная ссылка ManyToOne, потому что это более естественно, поскольку внешний ключ в любом случае находится в таблице, содержащей ManyToOne. Если вы внесете изменение, чтобы добавить ошибку в транзакцию, но не измените ошибку, чтобы также ссылаться на эту транзакцию, ваша объектная модель будет не синхронизирована с тем, что входит в базу данных - внешний ключ в Error не будет изменен, но объект транзакции будет показывать ошибку в своем списке до тех пор, пока он не будет обновлен или перезагружен из базы данных.

Каскадирование не связано с владением. Это просто означает, что операция (сохранение, слияние, удаление, обновление) применяется к сущности, на которую ссылается отношение. При использовании cascade.all вызова em.refresh (транзакция) транзакция и все связанные ошибки будут обновлены из базы данных. Любые ошибки отношений, которые имеют каскадную настройку ALL или REFRESH, также будут обновлены и так далее. JPA должен обнаружить, что он уже обновил указанный экземпляр транзакции, если вы поместите его в обратные ссылки, но зачем рисковать. Как правило, каскадные параметры следует размещать только там, где они требуются, чтобы избежать непредвиденных последствий. Если вы не уверены, что это нужно, оставьте его, пока не будете уверены. Такие вещи, как ленивая загрузка и другие оптимизации, могут вызывать всевозможные странные ошибки, которые трудно найти, когда кто-то идет и ставит каскадное обновление повсюду.

В вашем примере вы можете поместить каскадное слияние в корневой объект, который ваше приложение будет передавать. Любые изменения, внесенные в этот граф, легко подхватываются одним вызовом слияния без необходимости вызывать слияние для каждого отдельного листа. Однако то, как ваша модель построена и сериализована, повлияет на слияние, поэтому обычно параметры каскада помещаются только в отношения root-> Leaf, чтобы избежать проблем, когда root -> leaf -> root 'where root! = Root'. Если у вас есть каскадное слияние с обеих сторон, состояние root 'может перезаписать ваши изменения в root.

Большое спасибо за подробное объяснение и ваше время. Очень ценю информацию. Итак, в основном, что я получил из этого, так это, если убрать каскадирование из картины, обновление объекта (возникающее из слияния на отдельном объекте) будет отражаться только тогда, когда сторона-владелец выполняет вызов слияния. Как вы думаете, это верный вывод? Или владение означает, что эта сущность несет ответственность за поддержание правильного сопоставления с родительской сущностью, и это все?

worldbeater 01.09.2018 00:36

Другие вопросы по теме