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-domain-model.asciidoc 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. ---
  2. title: Defining a Domain Model
  3. order: 3
  4. layout: page
  5. ---
  6. [[jpacontainer.domain-model]]
  7. = Defining a Domain Model
  8. Developing a persistent application begins with defining a domain model. A
  9. domain model consists of a number of entities (classes) and relationships
  10. between them.
  11. <<figure.jpacontainer.domain-model>> illustrates a simple domain model as a UML
  12. class diagram. It has two entities: [classname]#Country# and
  13. [classname]#Person#. They have a "country has persons" relationship. This is a
  14. __one-to-many relationship__ with one country having many persons, each of which
  15. belongs to just one country.
  16. [[figure.jpacontainer.domain-model]]
  17. .A Domain Model
  18. image::img/domain-model-hi.png[]
  19. Realized in Java, the classes are as follows:
  20. ----
  21. public class Country {
  22. private Long id;
  23. private String name;
  24. private Set<Person> persons;
  25. ... setters and getters ...
  26. }
  27. public class Person {
  28. private Long id;
  29. private String name;
  30. private Integer age;
  31. private Country country;
  32. ... setters and getters ...
  33. }
  34. ----
  35. You should make the classes proper beans by defining a default constructor and
  36. implementing the [interfacename]#Serializable# interface. A default constructor
  37. is required by the JPA entity manager for instantiating entities. Having the
  38. classes serializable is not required but often useful for other reasons.
  39. After you have a basic domain model, you need to define the entity relationship
  40. metadata by annotating the classes.
  41. [[jpacontainer.domain-model.annotation]]
  42. == Persistence Metadata
  43. The entity relationships are defined with metadata. The metadata can be defined
  44. in an XML metadata file or with Java annotations defined in the
  45. [package]#javax.persistence# package. With Vaadin JPAContainer, you need to
  46. provide the metadata as annotations.
  47. For example, if we look at the Person class in the JPAContainer AddressBook
  48. Demo, we define various database-related metadata for the member variables of a
  49. class:
  50. ----
  51. @Entity
  52. public class Person {
  53. @Id
  54. @GeneratedValue(strategy = GenerationType.AUTO)
  55. private Long id;
  56. private String name;
  57. private Integer age;
  58. @ManyToOne
  59. private Country country;
  60. ----
  61. The JPA implementation uses reflection to read the annotations and defines a
  62. database model automatically from the class definitions.
  63. Let us look at some of the basic JPA metadata annotations. The annotations are
  64. defined in the [package]#javax.persistence# package. Please refer to JPA
  65. reference documentation for the complete list of possible annotations.
  66. [[jpacontainer.domain-model.metadata.entity]]
  67. === Annotation: [literal]#++@Entity++#
  68. Each class that is enabled as a persistent entity must have the
  69. [literal]#++@Entity++# annotation.
  70. ----
  71. @Entity
  72. public class Country {
  73. ----
  74. [[jpacontainer.domain-model.annotation.id]]
  75. === Annotation: [literal]#++@Id++#
  76. Entities must have an identifier that is used as the primary key for the table.
  77. It is used for various purposes in database queries, most commonly for joining
  78. tables.
  79. ----
  80. @Id
  81. @GeneratedValue(strategy = GenerationType.AUTO)
  82. private Long id;
  83. ----
  84. The identifier is generated automatically in the database. The strategy for
  85. generating the identifier is defined with the [literal]#++@GeneratedValue++#
  86. annotation. Any generation type should work.
  87. [[jpacontainer.domain-model.annotation.onetoone]]
  88. === Annotation: [literal]#++@OneToOne++#
  89. The [literal]#++@OneToOne++# annotation describes a one-to-one relationship
  90. where each entity of one type is associated with exactly one entity of another
  91. type. For example, the postal address of a person could be given as such.
  92. ----
  93. @OneToOne
  94. private Address address;
  95. ----
  96. When using the JPAContainer [classname]#FieldFactory# to automatically create
  97. fields for a form, the [literal]#++@OneToOne++# relationship generates a nested
  98. [classname]#Form# to edit the data. See
  99. <<dummy/../../../framework/jpacontainer/jpacontainer-fieldfactory#jpacontainer.fieldfactory,"Automatic
  100. Form Generation">> for more details.
  101. [[jpacontainer.domain-model.annotation.embedded]]
  102. === Annotation: [literal]#++@Embedded++#
  103. Just as with the [literal]#++@OneToOne++# annotation, [literal]#++@Embedded++#
  104. describes a one-to-one relationship, but says that the referenced entity should
  105. be stored as columns in the same table as the referencing entity.
  106. ----
  107. @Embedded
  108. private Address address;
  109. ----
  110. The referenced entity class must have [literal]#++@Embeddable++# annotation.
  111. The JPAContainer [classname]#FieldFactory# generates a nested [classname]#Form#
  112. for [literal]#++@Embedded++#, just as with [literal]#++@OneToOne++#.
  113. [[jpacontainer.domain-model.annotation.onetomany]]
  114. === Annotation: [literal]#++@OneToMany++#
  115. The [classname]#Country# entity in the domain model has a __one-to-many__
  116. relationship with the [classname]#Person# entity ("country has persons"). This
  117. relationship is represented with the [literal]#++@OneToMany++# annotation. The
  118. [parameter]#mappedBy# parameter names the corresponding back-reference in the
  119. [classname]#Person# entity.
  120. ----
  121. @OneToMany(mappedBy = "country")
  122. private Set<Person> persons;
  123. ----
  124. When using the JPAContainer [classname]#FieldFactory# to automatically create
  125. fields for a form, the [literal]#++@OneToMany++# relationship generates a
  126. [classname]#MasterDetailEditor# for editing the items. See
  127. <<dummy/../../../framework/jpacontainer/jpacontainer-fieldfactory#jpacontainer.fieldfactory,"Automatic
  128. Form Generation">> for more details.
  129. [[jpacontainer.domain-model.annotation.elementcollection]]
  130. === Annotation: [literal]#++@ElementCollection++#
  131. The [literal]#++@ElementCollection++# annotation can be used for one-to-many
  132. relationships to a collection of basic values such as [classname]#String# or
  133. [classname]#Integer#, or to entities annotated as [literal]#++@Embeddable++#.
  134. The referenced entities are stored in a separate table defined with a
  135. [literal]#++@CollectionTable++# annotation.
  136. ----
  137. @ElementCollection
  138. @CollectionTable(
  139. name="OLDPEOPLE",
  140. joinColumns=@JoinColumn(name="COUNTRY_ID"))
  141. private Set<Person> persons;
  142. ----
  143. JPAContainer [classname]#FieldFactory# generates a
  144. [classname]#MasterDetailEditor# for the [literal]#++@ElementCollection++#
  145. relationship, just as with [literal]#++@OneToMany++#.
  146. [[jpacontainer.domain-model.annotation.manytoone]]
  147. === Annotation: [literal]#++@ManyToOne++#
  148. Many people can live in the same country. This would be represented with the
  149. [literal]#++@ManyToOne++# annotation in the [classname]#Person# class.
  150. ----
  151. @ManyToOne
  152. private Country country;
  153. ----
  154. JPAContainer [classname]#FieldFactory# generates a [classname]#NativeSelect# for
  155. selecting an item from the collection. You can do so yourself as well in a
  156. custom field factory. Doing so you need to pay notice not to confuse the
  157. container between the referenced entity and its ID, which could even result in
  158. insertion of false entities in the database in some cases. You can handle
  159. conversion between an entity and the entity ID using the
  160. [classname]#SingleSelectConverter# as follows:
  161. ----
  162. @Override
  163. public <T extends Field> T createField(Class<?> dataType,
  164. Class<T> fieldType) {
  165. if (dataType == Country.class) {
  166. JPAContainer<Country> countries =
  167. JPAContainerFactory.make(Country.class, "mypunit");
  168. ComboBox cb = new ComboBox(null, countries);
  169. cb.setConverter(new SingleSelectConverter<Country>(cb));
  170. return (T) cb;
  171. }
  172. return super.createField(dataType, fieldType);
  173. }
  174. ----
  175. The JPAContainer [classname]#FieldFactory# uses the translator internally, so
  176. using it also avoids the problem.
  177. [[jpacontainer.domain-model.annotation.transient]]
  178. === Annotation: [literal]#++@Transient++#
  179. JPA assumes that all entity properties are persisted. Properties that should not
  180. be persisted should be marked as transient with the [literal]#++@Transient++#
  181. annotation.
  182. ----
  183. @Transient
  184. private Boolean superDepartment;
  185. ...
  186. @Transient
  187. public String getHierarchicalName() {
  188. ...
  189. ----