JPA: Могу ли я принудительно сохранить объекты в базе данных в том порядке, в котором они были отправлены в persist ()? - PullRequest
1 голос
/ 25 сентября 2010

Я создаю биллинговую систему , которая управляет Главной книгой для каждого клиента.У каждой книги есть список LedgerEntry, в котором записывается каждая транзакция клиента.

Когда я проверял это, я заметил, что если я создал группу LedgerEntry в одной и той же транзакции, значение @Id было бы не такимобъекты были переданы em.persist (), если только я не создал em.flush () после создания каждой записи.

Поскольку я полагаюсь на порядок идентификатора для правильного поведения Главной книги (в частности,текущий баланс является последним LedgerEntry в списке - принудительно выполняется с помощью @OrderBy "id ASC"), это означает, что я должен выполнить flush () несколько раз.

Есть ли способ избежать сбросапосле каждой строки создается?То есть иметь какой-то порядок порядка сохранения объектов без использования @OrderColumn?

Ответы [ 4 ]

1 голос
/ 25 сентября 2010

Я не уверен, является ли это стандартным JPA или только Hibernate, но обратите внимание на разницу между persist() и save() в Hibernate.Начиная с документы (выделено мной):

  • persist() делает временный экземпляр постоянным.Однако не гарантирует, что значение идентификатора будет присвоено постоянному экземпляру немедленно, назначение может произойти во время сброса.
  • save () действительно гарантирует возвратидентификатор .Если для получения идентификатора необходимо выполнить INSERT (например, генератор «identity», а не «sequence»), эта INSERT происходит немедленно, независимо от того, находитесь ли вы внутри или вне транзакции.

    Поэтому, если вы используете save(), идентификаторы должны быть сгенерированы в порядке, который вы вызываете save().Если вставка только для получения идентификатора проблематична (для производительности и т. Д.), Вы можете выбрать другой генератор идентификаторов, который не требует попадания в базу данных.

0 голосов
/ 25 сентября 2010

И идентификаторы генерируются с помощью какого метода?последовательность?Таблица ?назначенный пользователем?Как указано в других ответах, нет гарантии порядка присваивания, , но , если метод генерации не зависит от хранилища данных, тогда большинство реализаций установит значение во время вызова «persist»,Если метод генерации OTOH использует хранилище данных, вам придется выполнить сброс, чтобы принудительно установить этот контакт хранилища данных.

0 голосов
/ 25 сентября 2010

Я не совсем уверен, что понимаю вашу структуру.

У вас должна быть возможность отсортировать одну бизнес-транзакцию (несколько строк LedgerEntry?) По транзакции_темпера, чтобы получить правильный порядок.

Но почему строка текущего баланса в таблице вообще? Это может быть вычислено, да?

Если в строке текущего баланса есть , я бы создал столбец line_item_number и назначил значения последовательно для каждой бизнес-операции. Это, вероятно, сделает хороший уникальный ключ в сочетании с идентификатором Ledger. И я присвоил бы текущей строке баланса магическое значение 999999, чтобы она всегда сортировалась последней.

Приятным побочным эффектом является то, что сбор суммы задолженности из таблицы очень прост - суммируйте все строки, где line_item_number = 999999.


Однако я предпочел бы удалить строку current_balance и посмотреть, как проблемы исчезнут.


Другой вариант - поместить компьютер current_balance в Ledger, а не в строку LedgerEntry.

0 голосов
/ 25 сентября 2010

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

Но на самом деле, если вам нужно разобраться с упорядоченным списком, IMO имеет смысл использовать столбец для поддержания постоянного порядка и определять его с помощью OrderColumn.ИМО не следует полагаться на ПК в деловых целях.

...