--- 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. <> 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 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 <> 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 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 <> 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 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 createField(Class dataType, Class fieldType) { if (dataType == Country.class) { JPAContainer countries = JPAContainerFactory.make(Country.class, "mypunit"); ComboBox cb = new ComboBox(null, countries); cb.setConverter(new SingleSelectConverter(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() { ... ----