Вставка с примитивным типом как идентификатор объекта

В JPA (реализация Hibernate) Какой тип лучше использовать в качестве идентификатора объекта: Тип в штучной упаковке (например, Integer) или Unboxed (например, int)?

Друг сказал, что вы должны использовать типы в штучной упаковке, потому что, когда вы создаете новый объект в своей программе, Hibernate видит, что идентификатор является null и понимает, что он должен создать новую строку в базе данных (в отличие от id не является null Hibernate может обновлять существующая строка в базе данных).

Но id моих сущностей был int и он работал хорошо без ошибок, и мы знаем, что значение по умолчанию для примитивных переменных экземпляра равно 0. Поэтому он сказал, что, возможно, hibernate рассматривает 0 как особый и предполагает, что объект является новым.

Ответ 1

Ну, мы используем непримитивы, и у нас есть веская причина. Например, многие наши поля, которые являются либо int/Integer имеют абсолютное значение для бизнеса, равное zero и являются абсолютно допустимыми. Например, подумайте о долговом поле - это более чем нормально, если поле равно zero, то есть у вас нет долгов.

Проблема в том, что с примитивами значение нуля является значением по умолчанию - поэтому вы можете случайно забыть его установить, например, через setDebt, таким образом, он может достигнуть вашей базы данных с тем значением, которое вы никогда не планировали туда. По этой причине мы используем Integer с некоторыми валидациями, которые никогда не должны быть нулями, например; но даже если мы забудем добавить правильные проверки, этот код потенциально будет разбит на исключение NullPointerException (желательно в тестах), и мне нравится исключение больше, чем несогласованные значения в базе данных.

Ответ 2

Кажется, что в текущей документации рекомендуется использовать Boxed Type.

Мы рекомендуем вам объявлять атрибуты идентификатора с постоянным именем в постоянных классах и использовать тип с нулевым значением (т.е. Не примитивный).

Ответ 3

Нет никакой разницы между примитивным (например, int) и его оболочкой (например, Integer) для идентификатора объекта. Оба действуют в соответствии со спецификацией JPA. Поставщик JPA достаточно умен, чтобы отслеживать состояние и жизненный цикл объекта. Когда идентификатор объекта равен 0 (примитивный тип) или NULL (тип-оболочка), поставщик JPA будет генерировать идентификатор для объекта, если настроен генератор идентификаторов. Zero не рассматривается как допустимый идентификатор объекта, если идентификатор автоматически сгенерирован.

Испытал оба случая с Cmobilecom JPA, и он работает одинаково хорошо. Конечно, никакой разницы в производительности не наблюдается.

Отказ от ответственности: Я являюсь разработчиком Cmobilecom JPA, простой JPA-версии для Java и Android.

Ответ 4

Я предпочитаю Boxed Type в модели сущности, потому что это дает гибкость в использовании Boxed Type в generics. Например, здесь модель Entity может иметь только тип, который распространяется на Serializable для id. Он будет полезен позже на уровне обслуживания, где мы можем выполнять различные операции с первичным ключом.

public interface BaseEntity<E extends Serializable> extends Serializable {
  E getId();
}

Модель объекта может быть похожа:

@Entity
public class PhoneNumber implements BaseEntity<Long> {
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "PHONE_NUMBER_ID")
  private Long id;

Ответ 5

Уникальные идентификаторы объектов и коллекций могут быть любого базового типа, кроме двоичных, blob и clob. (Также допускаются составные идентификаторы, см. Ниже).

Базовые типы значений имеют соответствующие константы типа, определенные на org.hibernate.Hibernate. Например, Hibernate.STRING представляет тип строки.

Ответ 6

Мы можем думать об этом так:

Когда мы имеем значение x :: Int, тогда "x" - это вычисление, которое при вычислении возвращает либо Int, либо будет нижним (неопределенным).

Когда программа запускается и вычисляется x, предположим, что она вычисляется до фактического значения Int (не снизу). Затем в будущем в любое время x оценивается, а не переделывает весь расчет, мы хотим получить только то значение, которое мы предварительно вычислили.

Мы делаем это для замены на thunk (вычисление), который вычисляет x с помощью thunk, который просто возвращает значение, которое было вычислено ранее.

Проблема в том, что каждый раз, когда вам нужно получить x в будущем, вы должны следовать этому указателю на (тривиальный) код, который возвращает значение. Это дорого, если вам нужны эти значения часто.

Введите неразмеченные значения. Unboxed value - это просто низкоуровневое значение, не обернутое внутри thunk. Это означает, что он строгий в том смысле, что он не может быть неопределенным без вашей программы, которая обязательно умирает.