Entity providers provide access to entities persisted in a data store. They are essentially wrappers over a JPA entity manager with optimizations and other features important when binding persistent data to a user interface.
The choise and use of entity providers is largely invisible if you create your
JPAContainer
instances with the
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 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 as local in the sense that they provide access to entities using a local JPA entity manager.
The CachingMutableLocalEntityProvider
is usually
recommended as the first choise for read-write access and
CachingLocalEntityProvider
for read-only access.
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
makeNonCachedReadOnly()
method in
JPAContainerFactory
.
Extends 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 Section 18.5.1, “Built-In Entity Providers”.
The provider can notify about updates to entities through the
EntityProviderChangeNotifier
interface.
A simple non-caching implementation of the
BatchableEntityProvider
interface. It
extends MutableLocalEntityProvider
and simply
passes itself to the 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.
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
makeReadOnly()
method in
JPAContainerFactory
.
Just like 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
make()
method in
JPAContainerFactory
.
This provider supports making updates in
batches. You need to implement a
BatchUpdateCallback
that does
all the updates and execute the batch by calling
batchUpdate()
on the provider.
The provider is an extension of the
CachingMutableLocalEntityProvider
that
implements the
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
makeBatchable()
method in
JPAContainerFactory
.
JPAContainer 2.0 introduced a new set of entity providers specifically for
working in a JEE6
environment. In a JEE environment,
you should use an entity manager provided by the application server and,
usually, JTA
transactions instead of transactions
provided by JPA. Entity providers in
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
EntityManager
and to a JTA transaction.
The JNDI providers work with almost no special configuration at all. The
JPAContainerFactory
has factory methods for
creating various JNDI provider types. The only thing that you commonly
need to do is to expose the EntityManager
to a JNDI address. By default, the JNDI providers look for the
EntityManager
from
"java:comp/env/persistence/em
". This can be done with the
following snippet in 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 "MYPU
" is the identifier of your persistence unit
defined in your persistence.xml
file.
If you choose to annotate your servlets (instead of using the
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 setJndiAddresses()
method. You can also define the location for the JTA
UserTransaction
, but that should be always
accessible from "java:comp/UserTransaction
" by the JEE6
specification.
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 @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.