Skip to content

Commit 72e3b9c

Browse files
committed
document AccessType as topical guide
1 parent 2e09b19 commit 72e3b9c

File tree

1 file changed

+86
-37
lines changed

1 file changed

+86
-37
lines changed

documentation/src/main/asciidoc/topical/accesstype/AccessType.adoc

Lines changed: 86 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,50 @@
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.
6284
Annotations on the getter associated with that field (if one/any) are ignored (although we do try to log warnings
6385
in 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,
109131
which 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:
120142
using `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-
138147
JPA allows declaring the "access type" to use via the `javax.persistence.Access` annotation which can be applied to
139148
either a class or a field/method. We will look at applying `javax.persistence.Access` to a field/method in the next
140149
section. 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
182191
defining 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

Comments
 (0)