Возможно ли иметь неизменяемые поля в Hibernate/JPA?

В нашем приложении нам нужно иметь поля, которые можно назначать только один раз.

Сначала мы думали инкапсулировать поля и сделать сеттеры приватными. Однако возникают некоторые вопросы:

  • Может ли Hibernate без общедоступного установщика сопоставить поле из базы данных?
  • Могу ли я удалить установщик и сделать поле изменяемым только в конструкторе объектов?
  • Наконец, есть ли какой-нибудь стандартный способ JPA сделать поле неизменным?

Заранее спасибо.


person Carlos Melo    schedule 29.10.2011    source источник


Ответы (5)


  • Объявление. 1: Я считаю, что JPA использует простые частные поля как для чтения, так и для записи, если аннотации помещаются в поля, а не в геттеры. Недавно я обнаружил, что Hibernate как основной поставщик JPA вообще не нуждается в методах get*() и set*(). Это было действительно поучительное решение, так как с самого начала я думал, что Hibernate нужны аксессуары. Итак, ответ таков: вам не нужны сеттеры в том, что касается Hibernate.

  • Объявление. 2: Однако обратите внимание, что Hibernate по-прежнему нуждается в конструкторе без аргументов, иначе он не сможет загрузить объекты с описательным исключением. Это также требование JPA.

  • Объявление. 3: Нет, нет. Помните, что ваши коллекции также должны быть неизменяемыми.

person Tomasz Nurkiewicz    schedule 29.10.2011
comment
Итак, для доступа к полю: private fields + Hibernate FIELD-доступ + без конструктора аргументов (для Hibernate) + конструктор аргументов (для создания неизменяемого объекта)? это все, @Tomasz? - person Kevin Meredith; 14.07.2014
comment
Я просто хочу добавить, что конструктор без аргументов может быть объявлен private. Таким образом, если у вас есть класс Point с двумя полями final: x и y, вы можете иметь один общедоступный конструктор Point(int x,int y) для использования клиентским кодом и частный конструктор Point(), используемый спящим режимом. Написание комментария, объясняющего назначение частного конструктора, было бы хорошей идеей. - person W.K.S; 26.08.2014
comment
@W.K.S еще лучше создать собственную аннотацию (например, @ForHibernate). Есть вероятность, что ваша IDE перестанет отмечать этот конструктор как неиспользуемый после добавления аннотации (по крайней мере, eclipse) - person korda; 11.04.2016

Пытаться

@Column(updatable = false)

И сделайте свой сеттер приватным. (Оставьте свой геттер общедоступным, если хотите)

Я думаю, что это лучшая практика.

PS: JPA использует доступ к полю, если вы аннотируете свои поля, и использует доступ к получателю/установщику, если вы аннотируете свой метод получения.

person KaiThomasWerther    schedule 30.10.2011
comment
К сожалению, это правда, но попытка обновить столбец просто проигнорирует поле, что приведет к ужасным ошибкам, если программист забудет об этом флаге и предположит, что он доступен для записи. - person tkruse; 23.02.2016

В JPA 2.0 у вас есть два способа определить, какие атрибуты должны быть сохранены:

  1. Access(FIELD) - имя полей сохраняется,
  2. Access(PROPERTY) - имя свойств сохраняется.

Если аннотация Access(-) не используется, решение о том, какой доступ будет использоваться, зависит от того, где вы поместите аннотацию @Id. Если вы поместите его рядом с вашим полем - будет использоваться Доступ (ПОЛЕ). Если вы поместите его рядом с вашим аксессором - будет использоваться Access(PROPERTY).

Поэтому, если вы используете Access(FIELD), вам не нужно иметь соответствующий метод доступа в стиле JavaBeans для определенного поля. У вас может быть частное поле с именем «myField» и общедоступный установщик для него с именем «public setBlahBlah(-)». JPA сохранит только «myField».

person Piotr Nowicki    schedule 29.10.2011

Пытаться

@Column(updatable = false)

Из джавадока:

Включен ли столбец в операторы SQL UPDATE, созданные поставщиком сохраняемости.

person bbviana    schedule 06.07.2013

Вы можете пометить объект аннотациями @Entity(mutable=false) или @Immutable для платформы, чтобы использовать этот факт для увеличения производительности при кэшировании и т. д. (спящий режим)

Затем вы можете использовать неизменяемый класс-оболочку следующим образом:

public class ImmutableStuff {
    private final FooField barValue;

    public ImmutableStuff(Stuff stuff) {
        barValue = stuff.barValue;
    }

    public FooField getBarValue(){
        return barValue;
    }
}
person Desmond Zhou    schedule 29.10.2011