diff options
author | elmot <elmot@vaadin.com> | 2015-09-25 16:40:44 +0300 |
---|---|---|
committer | elmot <elmot@vaadin.com> | 2015-09-25 16:40:44 +0300 |
commit | a1b265c318dbda4a213cec930785b81e4c0f7d2b (patch) | |
tree | b149daf5a4f50b4f6446c906047cf86495fe0433 /documentation/jpacontainer/jpacontainer-domain-model.asciidoc | |
parent | b9743a48a1bd0394f19c54ee938c6395a80f3cd8 (diff) | |
download | vaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.tar.gz vaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.zip |
Framework documentation IN
Change-Id: I767477c1fc3745f9e1f58075fe30c9ac8da63581
Diffstat (limited to 'documentation/jpacontainer/jpacontainer-domain-model.asciidoc')
-rw-r--r-- | documentation/jpacontainer/jpacontainer-domain-model.asciidoc | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/documentation/jpacontainer/jpacontainer-domain-model.asciidoc b/documentation/jpacontainer/jpacontainer-domain-model.asciidoc new file mode 100644 index 0000000000..4d5fe482bf --- /dev/null +++ b/documentation/jpacontainer/jpacontainer-domain-model.asciidoc @@ -0,0 +1,265 @@ +--- +title: Defining a Domain Model +order: 3 +layout: page +--- + +[[jpacontainer.domain-model]] += Defining a Domain Model + +Developing a persistent application begins with defining a domain model. A +domain model consists of a number of entities (classes) and relationships +between them. + +<<figure.jpacontainer.domain-model>> illustrates a simple domain model as a UML +class diagram. It has two entities: [classname]#Country# and +[classname]#Person#. They have a "country has persons" relationship. This is a +__one-to-many relationship__ with one country having many persons, each of which +belongs to just one country. + +[[figure.jpacontainer.domain-model]] +.A Domain Model +image::img/domain-model-hi.png[] + +Realized in Java, the classes are as follows: + + +---- +public class Country { + private Long id; + private String name; + private Set<Person> persons; + + ... setters and getters ... +} + +public class Person { + private Long id; + private String name; + private Integer age; + private Country country; + + ... setters and getters ... +} +---- + +You should make the classes proper beans by defining a default constructor and +implementing the [interfacename]#Serializable# interface. A default constructor +is required by the JPA entity manager for instantiating entities. Having the +classes serializable is not required but often useful for other reasons. + +After you have a basic domain model, you need to define the entity relationship +metadata by annotating the classes. + +[[jpacontainer.domain-model.annotation]] +== Persistence Metadata + +The entity relationships are defined with metadata. The metadata can be defined +in an XML metadata file or with Java annotations defined in the +[package]#javax.persistence# package. With Vaadin JPAContainer, you need to +provide the metadata as annotations. + +For example, if we look at the Person class in the JPAContainer AddressBook +Demo, we define various database-related metadata for the member variables of a +class: + + +---- +@Entity +public class Person { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + private Integer age; + + @ManyToOne + private Country country; +---- + +The JPA implementation uses reflection to read the annotations and defines a +database model automatically from the class definitions. + +Let us look at some of the basic JPA metadata annotations. The annotations are +defined in the [package]#javax.persistence# package. Please refer to JPA +reference documentation for the complete list of possible annotations. + +[[jpacontainer.domain-model.metadata.entity]] +=== Annotation: [literal]#++@Entity++# + +Each class that is enabled as a persistent entity must have the +[literal]#++@Entity++# annotation. + + +---- +@Entity +public class Country { +---- + + +[[jpacontainer.domain-model.annotation.id]] +=== Annotation: [literal]#++@Id++# + +Entities must have an identifier that is used as the primary key for the table. +It is used for various purposes in database queries, most commonly for joining +tables. + + +---- +@Id +@GeneratedValue(strategy = GenerationType.AUTO) +private Long id; +---- + +The identifier is generated automatically in the database. The strategy for +generating the identifier is defined with the [literal]#++@GeneratedValue++# +annotation. Any generation type should work. + + +[[jpacontainer.domain-model.annotation.onetoone]] +=== Annotation: [literal]#++@OneToOne++# + +The [literal]#++@OneToOne++# annotation describes a one-to-one relationship +where each entity of one type is associated with exactly one entity of another +type. For example, the postal address of a person could be given as such. + + +---- +@OneToOne +private Address address; +---- + +When using the JPAContainer [classname]#FieldFactory# to automatically create +fields for a form, the [literal]#++@OneToOne++# relationship generates a nested +[classname]#Form# to edit the data. See +<<dummy/../../../framework/jpacontainer/jpacontainer-fieldfactory#jpacontainer.fieldfactory,"Automatic +Form Generation">> for more details. + + +[[jpacontainer.domain-model.annotation.embedded]] +=== Annotation: [literal]#++@Embedded++# + +Just as with the [literal]#++@OneToOne++# annotation, [literal]#++@Embedded++# +describes a one-to-one relationship, but says that the referenced entity should +be stored as columns in the same table as the referencing entity. + + +---- +@Embedded +private Address address; +---- + +The referenced entity class must have [literal]#++@Embeddable++# annotation. + +The JPAContainer [classname]#FieldFactory# generates a nested [classname]#Form# +for [literal]#++@Embedded++#, just as with [literal]#++@OneToOne++#. + + +[[jpacontainer.domain-model.annotation.onetomany]] +=== Annotation: [literal]#++@OneToMany++# + +The [classname]#Country# entity in the domain model has a __one-to-many__ +relationship with the [classname]#Person# entity ("country has persons"). This +relationship is represented with the [literal]#++@OneToMany++# annotation. The +[parameter]#mappedBy# parameter names the corresponding back-reference in the +[classname]#Person# entity. + + +---- +@OneToMany(mappedBy = "country") +private Set<Person> persons; +---- + +When using the JPAContainer [classname]#FieldFactory# to automatically create +fields for a form, the [literal]#++@OneToMany++# relationship generates a +[classname]#MasterDetailEditor# for editing the items. See +<<dummy/../../../framework/jpacontainer/jpacontainer-fieldfactory#jpacontainer.fieldfactory,"Automatic +Form Generation">> for more details. + + +[[jpacontainer.domain-model.annotation.elementcollection]] +=== Annotation: [literal]#++@ElementCollection++# + +The [literal]#++@ElementCollection++# annotation can be used for one-to-many +relationships to a collection of basic values such as [classname]#String# or +[classname]#Integer#, or to entities annotated as [literal]#++@Embeddable++#. +The referenced entities are stored in a separate table defined with a +[literal]#++@CollectionTable++# annotation. + + +---- +@ElementCollection +@CollectionTable( + name="OLDPEOPLE", + joinColumns=@JoinColumn(name="COUNTRY_ID")) +private Set<Person> persons; +---- + +JPAContainer [classname]#FieldFactory# generates a +[classname]#MasterDetailEditor# for the [literal]#++@ElementCollection++# +relationship, just as with [literal]#++@OneToMany++#. + + +[[jpacontainer.domain-model.annotation.manytoone]] +=== Annotation: [literal]#++@ManyToOne++# + +Many people can live in the same country. This would be represented with the +[literal]#++@ManyToOne++# annotation in the [classname]#Person# class. + + +---- +@ManyToOne +private Country country; +---- + +JPAContainer [classname]#FieldFactory# generates a [classname]#NativeSelect# for +selecting an item from the collection. You can do so yourself as well in a +custom field factory. Doing so you need to pay notice not to confuse the +container between the referenced entity and its ID, which could even result in +insertion of false entities in the database in some cases. You can handle +conversion between an entity and the entity ID using the +[classname]#SingleSelectConverter# as follows: + + +---- + +@Override +public <T extends Field> T createField(Class<?> dataType, + Class<T> fieldType) { + if (dataType == Country.class) { + JPAContainer<Country> countries = + JPAContainerFactory.make(Country.class, "mypunit"); + ComboBox cb = new ComboBox(null, countries); + cb.setConverter(new SingleSelectConverter<Country>(cb)); + return (T) cb; + } + return super.createField(dataType, fieldType); +} +---- + +The JPAContainer [classname]#FieldFactory# uses the translator internally, so +using it also avoids the problem. + + +[[jpacontainer.domain-model.annotation.transient]] +=== Annotation: [literal]#++@Transient++# + +JPA assumes that all entity properties are persisted. Properties that should not +be persisted should be marked as transient with the [literal]#++@Transient++# +annotation. + + +---- +@Transient +private Boolean superDepartment; +... +@Transient +public String getHierarchicalName() { +... +---- + + + + + |