11= AccessType
22:toc:
33
4- Hibernate has always had a notion of "property access strategies" to allow users to control the runtime
5- access part. But JPA initially had no such concept. JPA 1 was quite inflexible in terms of where you
6- could place mapping annotations and in terms of telling the persistence provider how to access the values
7- (get/set them) of persistent attributes at runtime.
4+ `AccessType` refers to the JPA notion represented by the `javax.persistence.AccessType` enum. Even though
5+ AccessType is a single value, it actually represents 3 related concepts:
86
9- JPA 2.0 introduced the concept of `javax.persistence.AccessType` to allow better control over defining
10- where the persistence provider look for mapping annotations and how it access the attribute values at
11- runtime. JPA defines this at a number of "levels", so lets start there.
7+ # Determining which fields/methods constitute a persistent attribute.
8+ # Indicating where to look for mapping annotations for each persistent attribute.
9+ # How the attribute (its value) is accessed at runtime
1210
13- [NOTE]
14- ====
15- It is important to understand that generally speaking the phrase "access type" refers to a number of concepts:
11+ Unfortunately the JPA specification is not overly clear about how the AccessType value defines the
12+ answers to these 3 questions in all cases. Often that is left up to each provider to decide. So here we will
13+ discuss how Hibernate answers the 3 AccessType-related questions in different situations. By default, Hibernate
14+ tries to keep the explanation for how it answers these questions simple. AccessType defines 2 possible values: FIELD
15+ and PROPERTY.
1616
17- * Determining which fields/methods constitute a persistent attribute.
18- * Indicating where to look for mapping annotations for each persistent attribute.
19- * How the attribute (its value) is accessed at runtime
17+ For Hibernate, FIELD access means that:
18+
19+ # A persistent attribute is identified by its Class field
20+ # The mapping annotations for the persistent attribute are located on the Class field
21+ # At runtime we access the persistent attribute's value directly via the field.
22+
23+ PROPERTY access means that:
24+
25+ # A persistent attribute is identified by its JavaBeans-style getter and setter on a Class
26+ # The mapping annotations for the persistent attribute are located on the Class getter method
27+ # At runtime we access the persistent attribute's value via the getter/setter methods.
28+
29+ WARNING: Placing annotations on setters is NEVER appropriate.
2030
21- For the most part, Hibernate treats all 3 as being the same. There are some caveats here, which we will cover
22- as we go along.
23- ====
2431
32+ == Background
2533
26- == Default (hierarchy) level
34+ Hibernate has always had a notion of "property access strategies" to allow users to control the runtime access part.
35+ But, as back in those days there were no annotations and just XML-based mappings, the other 2 were never a concern.
36+ Initially JPA had no such explicit concept, although it did implicitly define runtime access based on placement of
37+ mapping annotations. JPA 2.0 introduced the concept of `javax.persistence.AccessType` to allow better control over
38+ defining where the persistence provider look for mapping annotations and how it access the attribute values at
39+ runtime. JPA allows defining AccessType at a number of "levels".
2740
28- Hibernate looks for the annotation marking the identifier of the entity hierarchy (either @Id or @EmbeddedId)
29- and uses its placement to determine the default "access type" for the hierarchy. Let's start with an example:
41+
42+ == Implicit (hierarchy) level
43+
44+ The implicit access type for an entity hierarchy defines how access type is defined when there is no explicitly
45+ defined AccessType. To determine implicit hierarchy access type, Hibernate looks for the annotation marking the
46+ identifier for the entity hierarchy (either @Id or @EmbeddedId). The placement (field or getter) defines the implicit
47+ access type for the hierarchy. Let's look at an example:
3048
3149
3250[[hierarchy-level-field]]
@@ -41,6 +59,9 @@ public class Document {
4159 private String title;
4260 @Lob
4361 private Clob content;
62+
63+ @Transient
64+ private int hashCode;
4465}
4566
4667@Entity
@@ -52,12 +73,13 @@ public class PublishedDocument extends Document {
5273----
5374====
5475
55- Here we have defaulted hierarchy-level field access because of the placement of @Id on a field, which means:
76+ Here we have implicit hierarchy-level field access because of the placement of @Id on a field, which means:
5677
5778* We look at the declared fields for each class to determine its persistent attributes. For the `Document` class,
58- we have 3 fields that would be considered persistent attributes: `id`, `title`, and `content`; for
79+ that means we have 3 fields that would be considered persistent attributes: `id`, `title`, and `content`; for
5980`PublishedDocument` we have 2: `isbn` and `publishDate`. Given field "access type", to indicate that a particular
60- field is not persistent, the field would be annotated with the `javax.persistence.Transient` annotation.
81+ field is not persistent, the field would be annotated with the `javax.persistence.Transient` annotation; here we
82+ see an example of that for the `hashCode` field.
6183* We use the annotations attached to those fields as the mapping annotations for the persistent attribute it indicates.
6284Annotations on the getter associated with that field (if one/any) are ignored (although we do try to log warnings
6385in such cases).
@@ -105,7 +127,7 @@ public class PublishedDocument extends Document {
105127----
106128====
107129
108- In this case, we have defaulted hierarchy-level property access because of the placement of @Id on the getter,
130+ In this case, we have implicit hierarchy-level property access because of the placement of @Id on the getter,
109131which here means:
110132
111133* We look at the declared methods for each class looking for JavaBean-style getters to determine the persistent
@@ -120,21 +142,8 @@ which here means:
120142using `java.lang.reflection.Method`.
121143
122144
123- WARNING: Placing annotations on setters is NEVER appropriate.
124-
125-
126- It is important to note that this is an implicit definition of "access type". This actually describes the
127- full support for defining "access type" in JPA 1.0. Which brings us to...
128-
129-
130145== Class level
131146
132- JPA 2.0 introduced a more explicit form of declaring "access type", represented by the `javax.persistence.AccessType`
133- enum defining 2 values:
134-
135- * FIELD
136- * PROPERTY
137-
138147JPA allows declaring the "access type" to use via the `javax.persistence.Access` annotation which can be applied to
139148either a class or a field/method. We will look at applying `javax.persistence.Access` to a field/method in the next
140149section. For now let's focus on the implications of applying it to a class.
@@ -144,7 +153,7 @@ access. But lets instead use `javax.persistence.Access` and see what affect tha
144153
145154
146155[[class-level-property]]
147- .Hierarchy -level FIELD access
156+ .Class -level PROPERTY access
148157====
149158[source, JAVA]
150159----
@@ -181,3 +190,43 @@ as the hierarchy default. But in terms of the `PublishedDocument` class, it has
181190<<hierarchy-level-property,second example>> in that we now look to the getters within the `PublishedDocument` as
182191defining persistent attributes and we use the getter and setter at runtime when access `PublishedDocument` attributes
183192(but not the attributes it inherits).
193+
194+ Similarly, the explicit class-level access type can be set to FIELD:
195+
196+ [[class-level-field]]
197+ .Class-level FIELD access
198+ ====
199+ [source, JAVA]
200+ ----
201+ @Entity
202+ public class Document {
203+ private Integer id;
204+ private String title;
205+ private Clob content;
206+
207+ @Id
208+ public Integer getId() { return id; }
209+ public void setId(Integer id) { this.id = id; }
210+
211+ public String getTitle() { return title; }
212+ public void setTitle(String title) { this.title = title; }
213+
214+ @Lob
215+ public Clob getContent() { return content; }
216+ public void setContent(Clob content) { this.content = content; }
217+ }
218+
219+ @Entity
220+ @Access(PROPERTY)
221+ public class PublishedDocument extends Document {
222+ private String isbn;
223+ @Temporal(DATE)
224+ private Date publishDate;
225+ }
226+ ----
227+ ====
228+
229+
230+ == Attribute-level
231+
232+ JPA also says that access type can be explicitly specified on an individual attribute...
0 commit comments