Подтвердить что ты не робот

Как сделать объект доступным только для чтения?

Каков правильный способ сделать Entity доступным только для чтения с JPA? Я хочу, чтобы моя таблица базы данных никогда не изменялась программно.

Думаю, я понимаю, что я должен блокировать свои объекты с помощью LockModeType.READ. Можно ли использовать аннотацию, чтобы мои объекты были заблокированы напрямую после извлечения из базы данных? Или мне нужно испортить и переопределить мой общий DAO для этого конкретного объекта?

4b9b3361

Ответ 1

Решение состоит в использовании аннотации на основе полей, чтобы объявить ваши поля как protected и предложить только публичный геттер. При этом ваши объекты не могут быть изменены.

(Это решение не является сущностью, это всего лишь способ создания неизменяемых объектов)

Ответ 2

В вашей сущности добавьте EntityListener, например, так:

@Entity
@EntityListeners(PreventAnyUpdate.class)
public class YourEntity {
    // ...
}

Реализуйте свой EntityListener, чтобы вызвать исключение, если произойдет какое-либо обновление:

public class PreventAnyUpdate {

    @PrePersist
    void onPrePersist(Object o) {
        throw new RuntimeException("...");
    }

    @PreUpdate
    void onPreUpdate(Object o) {
        throw new RuntimeException("...");
    }

    @PreRemove
    void onPreRemove(Object o) {
        throw new RuntimeException("...");
    }
}

Это создаст пуленепробиваемую сеть безопасности для вашей сущности со слушателями жизненного цикла JPA.

  • PRO: стандарт JPA - не специфичный для спящего режима
  • PRO: очень безопасно
  • CON: показывает только попытки записи во время выполнения. Если вы хотите проверить время компиляции, вы не должны реализовывать сеттеры.

Ответ 3

Если ваша реализация JPA находится в спящем режиме - вы можете использовать аннотацию спящего Entity

@org.hibernate.annotations.Entity(mutable = false)

Очевидно, это свяжет вашу модель с гибернацией.

Ответ 4

Hibernate также имеет аннотацию org.hibernate.annotations.Immutable, которую вы можете поместить в тип, метод или поле.

Ответ 5

Я думаю, что вы ищете, чтобы ваше лицо было неизменным. Hibernate поддерживает это; JPA (по крайней мере, JPA 1.0). Я полагаю, что вы можете контролировать это, предоставляя только геттеры и убедитесь, что геттеры возвращают только неизменные значения.

Ответ 6

IIRC вы можете установить каждое поле в insertable = false и updatable = false в аннотации @Column, но я уверен, что должен быть лучший метод...:)

Я не думаю, что это помогает?

Ответ 7

Реализация Eclipselink также предлагает аннотацию @ReadOnly на уровне сущности

Ответ 8

Это, вероятно, поймает меня на понижение, потому что я всегда склоняюсь вниз, чтобы предложить его, но вы можете использовать AspectJ несколькими способами для обеспечения этого:

Либо автоматизируйте решение Mac (сделайте AspectJ вставляйте аннотацию @Column):

declare @field : (@Entity *) *.* : @Column(insertable=false);

Или объявить ошибку компилятора для всех методов доступа к методам:

declare error : execution((@Entity *) *.set*(*) );

Даунсайд: вам нужно добавить компиляцию AspectJ в свою сборку, но это легко, если вы используете ant или maven

Ответ 9

Если вы используете spring-data или иным образом используете шаблон Repository, не включайте в репозиторий какие-либо методы save/update/create/insert/etc для этой конкретной сущности. Это можно обобщить, имея базовый класс/интерфейс для объектов, доступных только для чтения, и обновляемый объект, который расширяет класс, доступный только для чтения, для обновляемых объектов. Как отмечали другие авторы, сеттеры также могут быть недоступны для публики, чтобы разработчики не могли случайно установить значения, которые они затем не смогут сохранить.