123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- ---
- title: Basic Use of JPAContainer
- order: 4
- layout: page
- ---
-
- [[jpacontainer.usage]]
- = Basic Use of JPAContainer
-
- Vaadin JPAContainer offers a highly flexible API that makes things easy in
- simple cases while allowing extensive flexibility in demanding cases. To begin
- with, it is a [classname]#Container#, as described in
- <<dummy/../../../framework/datamodel/datamodel-container#datamodel.container,"Collecting
- Items in Containers">>.
-
- In this section, we look how to create and use [classname]#JPAContainer#
- instances. We assume that you have defined a domain model with JPA annotations,
- as described in the previous section.
-
- [[jpacontainer.usage.jpacontainerfactory]]
- == Creating [classname]#JPAContainer# with [classname]#JPAContainerFactory#
-
- The [classname]#JPAContainerFactory# is the easy way to create
- [classname]#JPAContainer#s. It provides a set of __make...()__ factory methods
- for most cases that you will likely meet. Each factory method uses a different
- type of entity provider, which are described in
- <<dummy/../../../framework/jpacontainer/jpacontainer-entityprovider#jpacontainer.entityprovider,"Entity
- Providers">>.
-
- The factory methods take the class type of the entity class as the first
- parameter. The second parameter is either a persistence unit name (persistence
- context) or an [classname]#EntityManager# instance.
-
-
- ----
- // Create a persistent person container
- JPAContainer<Person> persons =
- JPAContainerFactory.make(Person.class, "book-examples");
-
- // You can add entities to the container as well
- persons.addEntity(new Person("Marie-Louise Meilleur", 117));
-
- // Set up sorting if the natural order is not appropriate
- persons.sort(new String[]{"age", "name"},
- new boolean[]{false, false});
-
- // Bind it to a component
- Table personTable = new Table("The Persistent People", persons);
- personTable.setVisibleColumns("id","name","age");
- layout.addComponent(personTable);
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.basic[on-line example, window="_blank"].
-
- It's that easy. In fact, if you run the above code multiple times, you'll be
- annoyed by getting a new set of persons for each run - that's how persistent the
- container is. The basic [methodname]#make()# uses a
- [classname]#CachedMutableLocalEntityProvider#, which allows modifying the
- container and its entities, as we do above by adding new entities.
-
- When using just the persistence unit name, the factory creates an instance of
- [classname]#EntityManagerFactory# for the persistence unit and uses it to build
- entity managers. You can also create the entity managers yourself, as described
- later.
-
- The entity providers associated with the different factory methods are as
- follows:
-
- [[table.jpacontainer.usage.jpacontainerfactory]]
- .[classname]#JPAContainerFactory# Methods
-
- |===============
- |[methodname]#make()#|[classname]#CachingMutableLocalEntityProvider#
- |[methodname]#makeReadOnly()#|[classname]#CachingLocalEntityProvider#
- |[methodname]#makeBatchable()#|[classname]#BatchableLocalEntityProvider#
- |[methodname]#makeNonCached()#|[classname]#MutableLocalEntityProvider#
- |[methodname]#makeNonCachedReadOnly()#|[classname]#LocalEntityProvider#
-
- |===============
-
-
-
- [classname]#JPAContainerFactory# holds a cache of entity manager factories for
- the different persistence units, making sure that any entity manager factory is
- created only once, as it is a heavy operation. You can access the cache to get a
- new entity manager with the
- [methodname]#createEntityManagerForPersistenceUnit()# method.
-
-
- ----
- // Get an entity manager
- EntityManager em = JPAContainerFactory.
- createEntityManagerForPersistenceUnit("book-examples");
-
- // Do a query
- em.getTransaction().begin();
- em.createQuery("DELETE FROM Person p").executeUpdate();
- em.persist(new Person("Jeanne Calment", 122));
- em.persist(new Person("Sarah Knauss", 119));
- em.persist(new Person("Lucy Hannah", 117));
- em.getTransaction().commit();
-
- ...
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.basic[on-line example, window="_blank"].
-
- Notice that if you use update the persistent data with an entity manager outside
- a [classname]#JPAContainer# bound to the data, you need to refresh the container
- as described in <<jpacontainer.usage.entitites>>.
-
- [[jpacontainer.usage.jpacontainerfactory.thehardway]]
- === Creating [classname]#JPAContainer# Manually
-
- While it is normally easiest to use a [classname]#JPAContainerFactory# to create
- [classname]#JPAContainer# instances, you may need to create them manually. It is
- necessary, for example, when you need to use a custom entity provider or extend
- [classname]#JPAContainer#.
-
- First, we need to create an entity manager and then the entity provider, which
- we bind to a [classname]#JPAContainer#.
-
-
- ----
- // We need a factory to create entity manager
- EntityManagerFactory emf =
- Persistence.createEntityManagerFactory("book-examples");
-
- // We need an entity manager to create entity provider
- EntityManager em = emf.createEntityManager();
-
- // We need an entity provider to create a container
- CachingMutableLocalEntityProvider<Person> entityProvider =
- new CachingMutableLocalEntityProvider<Person>(Person.class,
- em);
-
- // And there we have it
- JPAContainer<Person> persons =
- new JPAContainer<Person> (Person.class);
- persons.setEntityProvider(entityProvider);
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.thehardway[on-line example, window="_blank"].
-
- You could save the first step by asking the entity manager from the
- [classname]#JPAContainerFactory#.
-
-
-
- [[jpacontainer.usage.entitites]]
- == Creating and Accessing Entities
-
- JPAContainer integrates with the JPA entity manager, which you would normally
- use to create and access entities with JPA. You can use the entity manager for
- any purposes you may have, and then [classname]#JPAContainer# to bind entities
- to user interface components such as [classname]#Table#, [classname]#Tree#, any
- selection components, or a [classname]#Form#.
-
- You can add new entities to a [classname]#JPAContainer# with the
- [methodname]#addEntity()# method. It returns the item ID of the new entity.
-
-
- ----
- Country france = new Country("France");
- Object itemId = countries.addEntity(france);
- ----
-
- The item ID used by [classname]#JPAContainer# is the value of the ID property
- (column) defined with the [literal]#++@Id++# annotation. In our
- [classname]#Country# entity, it would have [classname]#Long# type. It is
- generated by the entity manager when the entity is persisted and set with the
- setter for the ID proeprty.
-
- Notice that the [methodname]#addEntity()# method does __not__ attach the entity
- instance given as the parameter. Instead, it creates a new instance. If you need
- to use the entity for some purpose, you need to get the actual managed entity
- from the container. You can get it with the item ID returned by
- [methodname]#addEntity()#.
-
-
- ----
- // Create a new entity and add it to a container
- Country france = new Country("France");
- Object itemId = countries.addEntity(france);
-
- // Get the managed entity
- france = countries.getItem(itemId).getEntity();
-
- // Use the managed entity in entity references
- persons.addEntity(new Person("Jeanne Calment", 122, france));
- ----
-
- [[jpacontainer.usage.entitites.items]]
- === Entity Items
-
- The [methodname]#getItem()# method is defined in the normal Vaadin
- [interfacename]#Container# interface. It returns an [classname]#EntityItem#,
- which is a wrapper over the actual entity object. You can get the entity object
- with [methodname]#getEntity()#.
-
- An [classname]#EntityItem# can have a number of states: persistent, modified,
- dirty, and deleted. The dirty and deleted states are meaningful when using
- __container buffering__, while the modified state is meaningful when using
- __item buffering__. Both levels of buffering can be used together - user input
- is first written to the item buffer, then to the entity instance, and finally to
- the database.
-
- The [methodname]#isPersistent()# method tells if the item is actually
- persistent, that is, fetched from a persistent storage, or if it is just a
- transient entity created and buffered by the container.
-
- The [methodname]#isModified()# method checks whether the [classname]#EntityItem#
- has changes that are not yet committed to the entity instance. It is only
- relevant if the item buffering is enabled with [methodname]#setBuffered(true)#
- for the item.
-
- The [methodname]#isDirty()# method checks whether the entity object has been
- modified after it was fetched from the entity provider. The dirty state is
- possible only when buffering is enabled for the container.
-
- The [methodname]#isDeleted()# method checks whether the item has been marked for
- deletion with [methodname]#removeItem()# in a buffered container.
-
-
- [[jpacontainer.usage.entitites.refreshing]]
- === Refreshing JPAContainer
-
- In cases where you change [classname]#JPAContainer# items outside the container,
- for example by through an [interfacename]#EntityManager#, or when they change in
- the database, you need to refresh the container.
-
- The [interfacename]#EntityContainer# interface implemented by
- [classname]#JPAContainer# provides two methods to refresh a container. The
- [methodname]#refresh()# discards all container caches and buffers and refreshes
- all loaded items in the container. All changes made to items provided by the
- container are discarded. The [methodname]#refreshItem()# refreshes a single
- item.
-
-
-
- [[jpacontainer.usage.nested-properties]]
- == Nested Properties
-
- If you have a one-to-one or many-to-one relationship, you can define the
- properties of the referenced entity as __nested__ in a
- [classname]#JPAContainer#. This way, you can access the properties directly
- through the container of the first entity type as if they were its properties.
- The interface is the same as with [classname]#BeanContainer# described in
- <<dummy/../../../framework/datamodel/datamodel-container#datamodel.container.beancontainer,"BeanContainer">>.
- You just need to add each nested property with
- [methodname]#addNestedContainerProperty()# using dot-separated path to the
- property.
-
-
- ----
- // Have a persistent container
- JPAContainer<Person> persons =
- JPAContainerFactory.make(Person.class, "book-examples");
-
- // Add a nested property to a many-to-one property
- persons.addNestedContainerProperty("country.name");
-
- // Show the persons in a table, except the "country" column,
- // which is an object - show the nested property instead
- Table personTable = new Table("The Persistent People", persons);
- personTable.setVisibleColumns("name", "age", "country.name");
-
- // Have a nicer caption for the country.name column
- personTable.setColumnHeader("country.name", "Nationality");
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.nested[on-line example, window="_blank"].
-
- The result is shown in <<figure.jpacontainer.usage.nested-properties>>. Notice
- that the [literal]#++country++# property in the container remains after adding
- the nested property, so we had to make that column invisible. Alternatively, we
- could have redefined the [methodname]#toString()# method in the country object
- to show the name instead of an object reference.
-
- [[figure.jpacontainer.usage.nested-properties]]
- .Nested Properties
- image::img/nested-properties.png[]
-
- You can use the [literal]#++*++# wildcard to add all properties in a nested
- item, for example, " [literal]#++country.*++#".
-
-
- [[jpacontainer.usage.hierarchical]]
- == Hierarchical Container
-
- [classname]#JPAContainer# implements the [interfacename]#Container.Hierarchical#
- interface and can be bound to hierarchical components such as a
- [classname]#Tree# or [classname]#TreeTable#. The feature requires that the
- hierarchy is represented with a __parent__ property that refers to the parent
- item. At database level, this would be a column with IDs.
-
- The representation would be as follows:
-
-
- ----
- @Entity
- public class CelestialBody implements Serializable {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String name;
-
- @ManyToOne
- private CelestialBody parent;
- ...
- } ...
-
- // Create some entities
- CelestialBody sun = new CelestialBody("The Sun", null);
- CelestialBody mercury = new CelestialBody("Mercury", sun);
- CelestialBody venus = new CelestialBody("Venus", sun);
- CelestialBody earth = new CelestialBody("Earth", sun);
- CelestialBody moon = new CelestialBody("The Moon", earth);
- CelestialBody mars = new CelestialBody("Mars", sun);
- ...
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].
-
- You set up a [classname]#JPAContainer# to have hierarchy by calling
- [methodname]#setParentProperty()# with the name of the property that refers to
- the parent. Coincidentally, it is named " [literal]#++parent++#" in the example:
-
-
- ----
- // Create the container
- JPAContainer<CelestialBody> bodies =
- JPAContainerFactory.make(CelestialBody.class, "my-unit");
-
- // Set it up for hierarchical representation
- bodies.setParentProperty("parent");
-
- // Bind it to a hierarhical component
- Tree tree = new Tree("Celestial Bodies", bodies);
- tree.setItemCaptionMode(Tree.ITEM_CAPTION_MODE_PROPERTY);
- tree.setItemCaptionPropertyId("name");
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].
-
- You can use the [methodname]#rootItemIds()# to acquire the item IDs of the root
- elements with no parent.
-
-
- ----
- // Expand the tree
- for (Object rootId: bodies.rootItemIds())
- tree.expandItemsRecursively(rootId);
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].
-
- [[jpacontainer.usage.hierarchical.unsupported]]
- === Unsupported Hierarchical Features
-
- Using [methodname]#setParent()# in the container to define parenthood is not
- supported.
-
- Also, the current implementation does not support __setChildrenAllowed()__,
- which controls whether the user can expand a node by clicking a toggle. The
- toggle is by default visible for all nodes, even if they have no children. The
- method is not supported because it would require storing the information outside
- the entities. You can override [methodname]#areChildrenAllowed()# to implement
- the functionality using a custom logic.
-
-
- ----
- // Customize JPAContainer to define the logic for
- // displaying the node expansion indicator
- JPAContainer<CelestialBody> bodies =
- new JPAContainer<CelestialBody>(CelestialBody.class) {
- @Override
- public boolean areChildrenAllowed(Object itemId) {
- // Some simple logic
- return getChildren(itemId).size() > 0;
- }
- };
- bodies.setEntityProvider(
- new CachingLocalEntityProvider<CelestialBody>(
- CelestialBody.class, em));
- ----
- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].
-
-
-
-
|