Как сделать сущность доступной только для чтения?
Как правильно сделать объект только для чтения с JPA ? Я хочу, чтобы моя таблица базы данных никогда не изменялась программно.
Я думаю, что понимаю, что я должен заблокировать мои объекты с LockModeType.READ. Можно ли использовать аннотацию, чтобы сделать мои сущности непосредственно заблокированными после извлечения из базы данных ? Или мне нужно возиться и переопределять мой общий DAO для этой конкретной сущности ?
9 ответов:
решение заключается в использовании аннотации на основе полей, чтобы объявить ваши поля как
protectedи предлагать только публичный геттер. При этом ваши объекты не могут быть изменены.(это решение не является специфичным для сущности, это просто способ построения неизменяемых объектов)
вы можете создать пуленепробиваемую сеть безопасности для вашего объекта с прослушивателями жизненного цикла JPA.
- PRO: стандарт JPA - не hibernate specific
- PRO: очень безопасно
- CON: показывает только попытки записи runtime. Если вы хотите время компиляции проверьте, вы не должны реализовывать сеттеры.
в вашей сущности добавить
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 является hibernate - вы можете использовать аннотацию Hibernate Entity
@org.hibernate.annotations.Entity(mutable = false)очевидно, что это свяжет вашу модель в спящий режим, хотя.
Hibernate также имеет
org.hibernate.annotations.Immutableаннотация, которую можно поместить на тип, метод или поле.
Я думаю, что вы ищете, чтобы ваша сущность была неизменной. Hibernate поддерживает это; JPA (по крайней мере, JPA 1.0) этого не делает. Я полагаю, что вы можете контролировать это, предоставляя только геттеры и убедитесь, что геттеры возвращают только неизменяемые значения.
IIRC вы можете установить каждое поле в
insertable = falseиupdatable = falseв своем@Columnаннотации, но я уверен, что там должен быть лучший способ... :)не думаю этой помогает?
Это, вероятно, поймает меня downvote, потому что я всегда получаю downvoted за предложение, но вы могли бы использовать AspectJ несколькими способами добиться этого:
либо автоматизировать решение Mac (сделать AspectJ ввести
@Columnаннотация):declare @field : (@Entity *) *.* : @Column(insertable=false);или объявить ошибку компилятора для всех методов доступа к set:
declare error : execution((@Entity *) *.set*(*) );недостаток: вам нужно добавить компиляцию AspectJ в свою сборку, но это легко, если вы используете АНТ или maven
Если вы используете spring-data или иным образом используете шаблон репозитория, не включайте методы save / update / create / insert / etc в репозиторий для этого конкретного объекта. Это можно обобщить, имея базовый класс / интерфейс для объектов только для чтения и обновляемый, который расширяет только для чтения для обновляемых объектов. Как указывали другие плакаты, сеттеры также могут быть сделаны непубличными, чтобы разработчики случайно не устанавливали значения, которые они затем не удалось сохранить.
Comments