summaryrefslogtreecommitdiffstats
path: root/documentation/jpacontainer/jpacontainer-usage.asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/jpacontainer/jpacontainer-usage.asciidoc')
-rw-r--r--documentation/jpacontainer/jpacontainer-usage.asciidoc386
1 files changed, 386 insertions, 0 deletions
diff --git a/documentation/jpacontainer/jpacontainer-usage.asciidoc b/documentation/jpacontainer/jpacontainer-usage.asciidoc
new file mode 100644
index 0000000000..c4ba3b2a3f
--- /dev/null
+++ b/documentation/jpacontainer/jpacontainer-usage.asciidoc
@@ -0,0 +1,386 @@
+---
+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"].
+
+
+
+
+