You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

jpacontainer-usage.asciidoc 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. ---
  2. title: Basic Use of JPAContainer
  3. order: 4
  4. layout: page
  5. ---
  6. [[jpacontainer.usage]]
  7. = Basic Use of JPAContainer
  8. Vaadin JPAContainer offers a highly flexible API that makes things easy in
  9. simple cases while allowing extensive flexibility in demanding cases. To begin
  10. with, it is a [classname]#Container#, as described in
  11. <<dummy/../../../framework/datamodel/datamodel-container#datamodel.container,"Collecting
  12. Items in Containers">>.
  13. In this section, we look how to create and use [classname]#JPAContainer#
  14. instances. We assume that you have defined a domain model with JPA annotations,
  15. as described in the previous section.
  16. [[jpacontainer.usage.jpacontainerfactory]]
  17. == Creating [classname]#JPAContainer# with [classname]#JPAContainerFactory#
  18. The [classname]#JPAContainerFactory# is the easy way to create
  19. [classname]#JPAContainer#s. It provides a set of __make...()__ factory methods
  20. for most cases that you will likely meet. Each factory method uses a different
  21. type of entity provider, which are described in
  22. <<dummy/../../../framework/jpacontainer/jpacontainer-entityprovider#jpacontainer.entityprovider,"Entity
  23. Providers">>.
  24. The factory methods take the class type of the entity class as the first
  25. parameter. The second parameter is either a persistence unit name (persistence
  26. context) or an [classname]#EntityManager# instance.
  27. ----
  28. // Create a persistent person container
  29. JPAContainer<Person> persons =
  30. JPAContainerFactory.make(Person.class, "book-examples");
  31. // You can add entities to the container as well
  32. persons.addEntity(new Person("Marie-Louise Meilleur", 117));
  33. // Set up sorting if the natural order is not appropriate
  34. persons.sort(new String[]{"age", "name"},
  35. new boolean[]{false, false});
  36. // Bind it to a component
  37. Table personTable = new Table("The Persistent People", persons);
  38. personTable.setVisibleColumns("id","name","age");
  39. layout.addComponent(personTable);
  40. ----
  41. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.basic[on-line example, window="_blank"].
  42. It's that easy. In fact, if you run the above code multiple times, you'll be
  43. annoyed by getting a new set of persons for each run - that's how persistent the
  44. container is. The basic [methodname]#make()# uses a
  45. [classname]#CachedMutableLocalEntityProvider#, which allows modifying the
  46. container and its entities, as we do above by adding new entities.
  47. When using just the persistence unit name, the factory creates an instance of
  48. [classname]#EntityManagerFactory# for the persistence unit and uses it to build
  49. entity managers. You can also create the entity managers yourself, as described
  50. later.
  51. The entity providers associated with the different factory methods are as
  52. follows:
  53. [[table.jpacontainer.usage.jpacontainerfactory]]
  54. .[classname]#JPAContainerFactory# Methods
  55. |===============
  56. |[methodname]#make()#|[classname]#CachingMutableLocalEntityProvider#
  57. |[methodname]#makeReadOnly()#|[classname]#CachingLocalEntityProvider#
  58. |[methodname]#makeBatchable()#|[classname]#BatchableLocalEntityProvider#
  59. |[methodname]#makeNonCached()#|[classname]#MutableLocalEntityProvider#
  60. |[methodname]#makeNonCachedReadOnly()#|[classname]#LocalEntityProvider#
  61. |===============
  62. [classname]#JPAContainerFactory# holds a cache of entity manager factories for
  63. the different persistence units, making sure that any entity manager factory is
  64. created only once, as it is a heavy operation. You can access the cache to get a
  65. new entity manager with the
  66. [methodname]#createEntityManagerForPersistenceUnit()# method.
  67. ----
  68. // Get an entity manager
  69. EntityManager em = JPAContainerFactory.
  70. createEntityManagerForPersistenceUnit("book-examples");
  71. // Do a query
  72. em.getTransaction().begin();
  73. em.createQuery("DELETE FROM Person p").executeUpdate();
  74. em.persist(new Person("Jeanne Calment", 122));
  75. em.persist(new Person("Sarah Knauss", 119));
  76. em.persist(new Person("Lucy Hannah", 117));
  77. em.getTransaction().commit();
  78. ...
  79. ----
  80. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.basic[on-line example, window="_blank"].
  81. Notice that if you use update the persistent data with an entity manager outside
  82. a [classname]#JPAContainer# bound to the data, you need to refresh the container
  83. as described in <<jpacontainer.usage.entitites>>.
  84. [[jpacontainer.usage.jpacontainerfactory.thehardway]]
  85. === Creating [classname]#JPAContainer# Manually
  86. While it is normally easiest to use a [classname]#JPAContainerFactory# to create
  87. [classname]#JPAContainer# instances, you may need to create them manually. It is
  88. necessary, for example, when you need to use a custom entity provider or extend
  89. [classname]#JPAContainer#.
  90. First, we need to create an entity manager and then the entity provider, which
  91. we bind to a [classname]#JPAContainer#.
  92. ----
  93. // We need a factory to create entity manager
  94. EntityManagerFactory emf =
  95. Persistence.createEntityManagerFactory("book-examples");
  96. // We need an entity manager to create entity provider
  97. EntityManager em = emf.createEntityManager();
  98. // We need an entity provider to create a container
  99. CachingMutableLocalEntityProvider<Person> entityProvider =
  100. new CachingMutableLocalEntityProvider<Person>(Person.class,
  101. em);
  102. // And there we have it
  103. JPAContainer<Person> persons =
  104. new JPAContainer<Person> (Person.class);
  105. persons.setEntityProvider(entityProvider);
  106. ----
  107. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.thehardway[on-line example, window="_blank"].
  108. You could save the first step by asking the entity manager from the
  109. [classname]#JPAContainerFactory#.
  110. [[jpacontainer.usage.entitites]]
  111. == Creating and Accessing Entities
  112. JPAContainer integrates with the JPA entity manager, which you would normally
  113. use to create and access entities with JPA. You can use the entity manager for
  114. any purposes you may have, and then [classname]#JPAContainer# to bind entities
  115. to user interface components such as [classname]#Table#, [classname]#Tree#, any
  116. selection components, or a [classname]#Form#.
  117. You can add new entities to a [classname]#JPAContainer# with the
  118. [methodname]#addEntity()# method. It returns the item ID of the new entity.
  119. ----
  120. Country france = new Country("France");
  121. Object itemId = countries.addEntity(france);
  122. ----
  123. The item ID used by [classname]#JPAContainer# is the value of the ID property
  124. (column) defined with the [literal]#++@Id++# annotation. In our
  125. [classname]#Country# entity, it would have [classname]#Long# type. It is
  126. generated by the entity manager when the entity is persisted and set with the
  127. setter for the ID proeprty.
  128. Notice that the [methodname]#addEntity()# method does __not__ attach the entity
  129. instance given as the parameter. Instead, it creates a new instance. If you need
  130. to use the entity for some purpose, you need to get the actual managed entity
  131. from the container. You can get it with the item ID returned by
  132. [methodname]#addEntity()#.
  133. ----
  134. // Create a new entity and add it to a container
  135. Country france = new Country("France");
  136. Object itemId = countries.addEntity(france);
  137. // Get the managed entity
  138. france = countries.getItem(itemId).getEntity();
  139. // Use the managed entity in entity references
  140. persons.addEntity(new Person("Jeanne Calment", 122, france));
  141. ----
  142. [[jpacontainer.usage.entitites.items]]
  143. === Entity Items
  144. The [methodname]#getItem()# method is defined in the normal Vaadin
  145. [interfacename]#Container# interface. It returns an [classname]#EntityItem#,
  146. which is a wrapper over the actual entity object. You can get the entity object
  147. with [methodname]#getEntity()#.
  148. An [classname]#EntityItem# can have a number of states: persistent, modified,
  149. dirty, and deleted. The dirty and deleted states are meaningful when using
  150. __container buffering__, while the modified state is meaningful when using
  151. __item buffering__. Both levels of buffering can be used together - user input
  152. is first written to the item buffer, then to the entity instance, and finally to
  153. the database.
  154. The [methodname]#isPersistent()# method tells if the item is actually
  155. persistent, that is, fetched from a persistent storage, or if it is just a
  156. transient entity created and buffered by the container.
  157. The [methodname]#isModified()# method checks whether the [classname]#EntityItem#
  158. has changes that are not yet committed to the entity instance. It is only
  159. relevant if the item buffering is enabled with [methodname]#setBuffered(true)#
  160. for the item.
  161. The [methodname]#isDirty()# method checks whether the entity object has been
  162. modified after it was fetched from the entity provider. The dirty state is
  163. possible only when buffering is enabled for the container.
  164. The [methodname]#isDeleted()# method checks whether the item has been marked for
  165. deletion with [methodname]#removeItem()# in a buffered container.
  166. [[jpacontainer.usage.entitites.refreshing]]
  167. === Refreshing JPAContainer
  168. In cases where you change [classname]#JPAContainer# items outside the container,
  169. for example by through an [interfacename]#EntityManager#, or when they change in
  170. the database, you need to refresh the container.
  171. The [interfacename]#EntityContainer# interface implemented by
  172. [classname]#JPAContainer# provides two methods to refresh a container. The
  173. [methodname]#refresh()# discards all container caches and buffers and refreshes
  174. all loaded items in the container. All changes made to items provided by the
  175. container are discarded. The [methodname]#refreshItem()# refreshes a single
  176. item.
  177. [[jpacontainer.usage.nested-properties]]
  178. == Nested Properties
  179. If you have a one-to-one or many-to-one relationship, you can define the
  180. properties of the referenced entity as __nested__ in a
  181. [classname]#JPAContainer#. This way, you can access the properties directly
  182. through the container of the first entity type as if they were its properties.
  183. The interface is the same as with [classname]#BeanContainer# described in
  184. <<dummy/../../../framework/datamodel/datamodel-container#datamodel.container.beancontainer,"BeanContainer">>.
  185. You just need to add each nested property with
  186. [methodname]#addNestedContainerProperty()# using dot-separated path to the
  187. property.
  188. ----
  189. // Have a persistent container
  190. JPAContainer<Person> persons =
  191. JPAContainerFactory.make(Person.class, "book-examples");
  192. // Add a nested property to a many-to-one property
  193. persons.addNestedContainerProperty("country.name");
  194. // Show the persons in a table, except the "country" column,
  195. // which is an object - show the nested property instead
  196. Table personTable = new Table("The Persistent People", persons);
  197. personTable.setVisibleColumns("name", "age", "country.name");
  198. // Have a nicer caption for the country.name column
  199. personTable.setColumnHeader("country.name", "Nationality");
  200. ----
  201. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.nested[on-line example, window="_blank"].
  202. The result is shown in <<figure.jpacontainer.usage.nested-properties>>. Notice
  203. that the [literal]#++country++# property in the container remains after adding
  204. the nested property, so we had to make that column invisible. Alternatively, we
  205. could have redefined the [methodname]#toString()# method in the country object
  206. to show the name instead of an object reference.
  207. [[figure.jpacontainer.usage.nested-properties]]
  208. .Nested Properties
  209. image::img/nested-properties.png[]
  210. You can use the [literal]#++*++# wildcard to add all properties in a nested
  211. item, for example, " [literal]#++country.*++#".
  212. [[jpacontainer.usage.hierarchical]]
  213. == Hierarchical Container
  214. [classname]#JPAContainer# implements the [interfacename]#Container.Hierarchical#
  215. interface and can be bound to hierarchical components such as a
  216. [classname]#Tree# or [classname]#TreeTable#. The feature requires that the
  217. hierarchy is represented with a __parent__ property that refers to the parent
  218. item. At database level, this would be a column with IDs.
  219. The representation would be as follows:
  220. ----
  221. @Entity
  222. public class CelestialBody implements Serializable {
  223. @Id
  224. @GeneratedValue(strategy = GenerationType.IDENTITY)
  225. private Long id;
  226. private String name;
  227. @ManyToOne
  228. private CelestialBody parent;
  229. ...
  230. } ...
  231. // Create some entities
  232. CelestialBody sun = new CelestialBody("The Sun", null);
  233. CelestialBody mercury = new CelestialBody("Mercury", sun);
  234. CelestialBody venus = new CelestialBody("Venus", sun);
  235. CelestialBody earth = new CelestialBody("Earth", sun);
  236. CelestialBody moon = new CelestialBody("The Moon", earth);
  237. CelestialBody mars = new CelestialBody("Mars", sun);
  238. ...
  239. ----
  240. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].
  241. You set up a [classname]#JPAContainer# to have hierarchy by calling
  242. [methodname]#setParentProperty()# with the name of the property that refers to
  243. the parent. Coincidentally, it is named " [literal]#++parent++#" in the example:
  244. ----
  245. // Create the container
  246. JPAContainer<CelestialBody> bodies =
  247. JPAContainerFactory.make(CelestialBody.class, "my-unit");
  248. // Set it up for hierarchical representation
  249. bodies.setParentProperty("parent");
  250. // Bind it to a hierarhical component
  251. Tree tree = new Tree("Celestial Bodies", bodies);
  252. tree.setItemCaptionMode(Tree.ITEM_CAPTION_MODE_PROPERTY);
  253. tree.setItemCaptionPropertyId("name");
  254. ----
  255. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].
  256. You can use the [methodname]#rootItemIds()# to acquire the item IDs of the root
  257. elements with no parent.
  258. ----
  259. // Expand the tree
  260. for (Object rootId: bodies.rootItemIds())
  261. tree.expandItemsRecursively(rootId);
  262. ----
  263. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].
  264. [[jpacontainer.usage.hierarchical.unsupported]]
  265. === Unsupported Hierarchical Features
  266. Using [methodname]#setParent()# in the container to define parenthood is not
  267. supported.
  268. Also, the current implementation does not support __setChildrenAllowed()__,
  269. which controls whether the user can expand a node by clicking a toggle. The
  270. toggle is by default visible for all nodes, even if they have no children. The
  271. method is not supported because it would require storing the information outside
  272. the entities. You can override [methodname]#areChildrenAllowed()# to implement
  273. the functionality using a custom logic.
  274. ----
  275. // Customize JPAContainer to define the logic for
  276. // displaying the node expansion indicator
  277. JPAContainer<CelestialBody> bodies =
  278. new JPAContainer<CelestialBody>(CelestialBody.class) {
  279. @Override
  280. public boolean areChildrenAllowed(Object itemId) {
  281. // Some simple logic
  282. return getChildren(itemId).size() > 0;
  283. }
  284. };
  285. bodies.setEntityProvider(
  286. new CachingLocalEntityProvider<CelestialBody>(
  287. CelestialBody.class, em));
  288. ----
  289. See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.hierarchical[on-line example, window="_blank"].