24. Для чего нужна аннотация @Access?
UNKNOWNHibernate или другой провайдер должен каким-то образом получать доступ к полям сущности. Например, при сохранении сущности в базу данных Hibernate должен получить доступ к состоянию сущности, то есть прочитать значения полей сущности, чтобы записать их в соответствующие ячейки таблицы.
Аналогично при получении данных из БД и формировании из них объекта сущности, Hibernate должен создать этот самый объект сущности (для этого ему и нужен public или protected конструктор без параметров), а затем записать в поля этого объекта значения, полученные из ячеек БД, тем самым сформировав состояние сущности. Для чтения и записи этих полей Hibernate использует два подхода:
- Field access (доступ по полям). При таком способе аннотации маппинга (Id, Column, OneToMany, … ) размещаются над полями, и Hibernate напрямую работает с полями сущности, читая и записывая их.
- Property access (доступ по свойствам). При таком способе аннотации размещаются над методами-геттерами, но никак не над сеттерами. Hibernate использует их и сеттеры для чтения и записи полей сущности. Но есть требование - у сущности с property access названия методов должны соответствовать требованиям JavaBeans. Например, если у сущности Customer есть поле с именем firstName, то у этой сущности должны быть определены методы getFirstName и setFirstName для чтения и записи поля firstName.
Совокупность полей и методов (свойств) сущности называется атрибутами.
Эти два подхода неявно определяют тип доступа к состоянию конкретной сущности - либо доступ по полям либо доступ по свойствам. Но при неявном определении типа доступа JPA требует, чтобы у всех сущностей в иерархии был единый тип доступа.
По умолчанию тип доступа определяется местом, в котором находится аннотация @Id. Если она будет над полем - это будет AccessType.FIELD, если над геттером - это AccessType.PROPERTY.
Чтобы явно определить тип доступа у сущности, нужно использовать аннотацию @Access, которая может быть указана у сущности, Mapped Superclass и Embeddable class, а также над полями или методами.
Аннотация @Access позволяет в иерархии сущностей с одним единым типом доступа безболезненно определить для одной или нескольких сущностей другой тип доступа. То есть в иерархии, где у всех тип доступа, например, field access, можно у какой-нибудь сущности указать тип доступа property access и это не нарушит работу Hibernate.
Если у сущности объявлена аннотация @Access(AccessType.FIELD):
- значит аннотации маппинга нужно размещать над полями;
- есть возможность у любых атрибутов сущности поменять тип доступа на property access, разместив аннотацию @Access(AccessType.PROPERTY) над соответствующими геттерами;
- разместив аннотации маппинга над методами, не имеющими @Access(AccessType.PROPERTY), получим неопределенное поведение.
Если у сущности объявлена аннотация @Access(AccessType.PROPERTY):
- значит аннотации маппинга нужно размещать над геттерами;
- есть возможность у любых атрибутов сущности поменять тип доступа на field access, разместив аннотацию @Access(AccessType.FIELD) над соответствующими полями;
- разместив аннотации маппинга над полями, не имеющими @Access(AccessType.FIELD), получим неопределенное поведение.
Поля, унаследованные от суперкласса, имеют тип доступа этого суперкласса, а не дочерней сущности, даже если они не совпадают.
Когда у одной сущности определены разные типы доступа, то нужно использовать аннотацию @Transient для избежания дублирования маппинга.
Предыдущий вопрос: 23. Для чего нужна аннотация @Column?
Следующий вопрос: 25. Для чего нужна аннотация @Cacheable?
Все вопросы по теме: список
Все темы: список
Вопросы/замечания/предложения/нашли ошибку: напишите мне