123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- ---
- 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() {
- ...
- ----
-
-
-
-
|