1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
---
title: Entity Providers
order: 5
layout: page
---
[[jpacontainer.entityprovider]]
= Entity Providers
Entity providers provide access to entities persisted in a data store. They are
essentially wrappers over a JPA entity manager, adding optimizations and other
features important when binding persistent data to a user interface.
The choice and use of entity providers is largely invisible if you create your
[classname]#JPAContainer# instances with the [classname]#JPAContainerFactory#,
which hides such details.
JPAContainer entity providers can be customized, which is necessary for some
purposes. Entity providers can be Enterprise JavaBeans (EJBs), which is useful
when you use them in a Java EE application server.
[[jpacontainer.entityprovider.built-in]]
== Built-In Entity Providers
JPAContainer includes various kinds of built-in entity providers: caching and
non-caching, read-write and read-only, and batchable.
__Caching__ is useful for performance, but takes some memory for the cache and
makes the provider stateful. __Batching__, that is, running updates in larger
batches, can also enhance performance and be used together with caching. It is
stateless, but doing updates is a bit more complex than otherwise.
Using a __read-only__ container is preferable if read-write capability is not
needed.
All built-in providers are __local__ in the sense that they provide access to
entities using a local JPA entity manager.
The [classname]#CachingMutableLocalEntityProvider# is usually recommended as the
first choise for read-write access and [classname]#CachingLocalEntityProvider#
for read-only access.
=== [classname]#LocalEntityProvider#
A read-only, lazy loading entity provider that does not perform caching and
reads its data directly from an entity manager.
You can create the provider with [methodname]#makeNonCachedReadOnly()# method in
[classname]#JPAContainerFactory#.
=== [classname]#MutableLocalEntityProvider#
Extends [classname]#LocalEntityProvider# with write support. All changes are
directly sent to the entity manager.
Transactions can be handled either internally by the provider, which is the
default, or by the container. In the latter case, you can extend the class and
annotate it, for example, as described in
<<jpacontainer.entityprovider.built-in>>.
The provider can notify about updates to entities through the
[interfacename]#EntityProviderChangeNotifier# interface.
=== [classname]#BatchableLocalEntityProvider#
A simple non-caching implementation of the
[interfacename]#BatchableEntityProvider# interface. It extends
[classname]#MutableLocalEntityProvider# and simply passes itself to the
[methodname]#batchUpdate()# callback method. This will work properly if the
entities do not contain any references to other entities that are managed by the
same container.
=== [classname]#CachingLocalEntityProvider#
A read-only, lazy loading entity provider that caches both entities and query
results for different filter/sortBy combinations. When the cache gets full, the
oldest entries in the cache are removed. The maximum number of entities and
entity IDs to cache for each filter/sortBy combination can be configured in the
provider. The cache can also be manually flushed. When the cache grows full, the
oldest items are removed.
You can create the provider with [methodname]#makeReadOnly()# method in
[classname]#JPAContainerFactory#.
=== [classname]#CachingMutableLocalEntityProvider#
Just like [classname]#CachingLocalEntityProvider#, but with read-write access.
For read access, caching works just like in the read-only provider. When an
entity is added or updated, the cache is flushed in order to make sure the added
or updated entity shows up correctly when using filters and/or sorting. When an
entity is removed, only the filter/sortBy-caches that actually contain the item
are flushed.
This is perhaps the most commonly entity provider that you should consider using
for most tasks. You can create it with the [methodname]#make()# method in
[classname]#JPAContainerFactory#.
=== [classname]#CachingBatchableLocalEntityProvider#
This provider supports making updates in __batches__. You need to implement a
[interfacename]#BatchUpdateCallback# that does all the updates and execute the
batch by calling [methodname]#batchUpdate()# on the provider.
The provider is an extension of the
[classname]#CachingMutableLocalEntityProvider# that implements the
[interfacename]#BatchableEntityProvider# interface. This will work properly if
the entities do not contain any references to other entities that are managed by
the same container.
You can create the provider with [methodname]#makeBatchable()# method in
[classname]#JPAContainerFactory#.
[[jpacontainer.entityprovider.jndi]]
== Using JNDI Entity Providers in JEE6 Environment
JPAContainer 2.0 introduced a new set of entity providers specifically for
working in a [literal]#++JEE6++# environment. In a JEE environment, you should
use an entity manager provided by the application server and, usually,
[literal]#++JTA++# transactions instead of transactions provided by JPA. Entity
providers in [package]#com.vaadin.addon.jpacontainer.provider.jndijta# package
work mostly the same way as the normal providers discussed earlier, but use JNDI
lookups to get reference to an [interfacename]#EntityManager# and to a JTA
transaction.
The JNDI providers work with almost no special configuration at all. The
[classname]#JPAContainerFactory# has factory methods for creating various JNDI
provider types. The only thing that you commonly need to do is to expose the
[interfacename]#EntityManager# to a JNDI address. By default, the JNDI providers
look for the [interfacename]#EntityManager# from "
java:comp/env/persistence/em". This can be done with the following snippet in
[filename]#web.xml# or with similar configuration with annotations.
----
<persistence-context-ref>
<persistence-context-ref-name>
persistence/em
</persistence-context-ref-name>
<persistence-unit-name>MYPU</persistence-unit-name>
</persistence-context-ref>
----
The " [literal]#++MYPU++#" is the identifier of your persistence unit defined in
your [filename]#persistence.xml# file.
If you choose to annotate your servlets (instead of using the
[filename]#web.xml# file as described above), you can simply add the following
annotation to your servlet.
----
@PersistenceContext(name="persistence/em",unitName="MYPU")
----
If you wish to use another address for the persistence context, you can define
them with the [methodname]#setJndiAddresses()# method. You can also define the
location for the JTA [classname]#UserTransaction#, but that should be always
accessible from " java:comp/UserTransaction" by the JEE6 specification.
[[jpacontainer.entityprovider.ejb]]
== Entity Providers as Enterprise Beans
Entity providers can be Enterprise JavaBeans (EJB). This may be useful if you
use JPAContainer in a Java EE application server. In such case, you need to
implement a custom entity provider that allows the server to inject the entity
manager.
For example, if you need to use Java Transaction API (JTA) for JPA transactions,
you can implement such entity provider as follows. Just extend a built-in entity
provider of your choise and annotate the entity manager member as
[literal]#++@PersistenceContext++#. Entity providers can be either stateless or
stateful session beans. If you extend a caching entity provider, it has to be
stateful.
----
@Stateless
@TransactionManagement
public class MyEntityProviderBean extends
MutableLocalEntityProvider<MyEntity> {
@PersistenceContext
private EntityManager em;
protected LocalEntityProviderBean() {
super(MyEntity.class);
setTransactionsHandledByProvider(false);
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
protected void runInTransaction(Runnable operation) {
super.runInTransaction(operation);
}
@PostConstruct
public void init() {
setEntityManager(em);
/*
* The entity manager is transaction-scoped, which means
* that the entities will be automatically detached when
* the transaction is closed. Therefore, we do not need
* to explicitly detach them.
*/
setEntitiesDetached(false);
}
}
----
If you have more than one EJB provider, you might want to create an abstract
super class of the above and only define the entity type in implementations. You
can implement an entity provider as a managed bean in Spring Framefork the same
way.
|