Вставка с примитивным типом как идентификатор объекта
В 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. Это означает, что он строгий в том смысле, что он не может быть неопределенным без вашей программы, которая обязательно умирает.