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

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

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

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

Спасибо заранее.

Ответ 1

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

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

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

Ответ 2

Try

@Column(updatable = false)

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

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

P.S.: JPA использует доступ к полям, если вы аннотируете свои поля и используете доступ к getter/setter, если вы комментируете свой метод getter.

Ответ 3

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

  • Доступ (FIELD) - имя поля сохраняется,
  • Доступ (PROPERTY) - имя свойства сохраняется.

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

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

Ответ 4

Попробуйте

@Column(updatable = false)

Из javadoc:

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

Ответ 5

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

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

public class ImmutableStuff {
    private final FooField barValue;

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

    public FooField getBarValue(){
        return barValue;
    }
}