Domain Models

Domain modeling is a concept inseparably linked with persistence, it is in fact the domain model that is persisted. There are four key areas regarding the domain model

This section deals with the defining aspect, the other three areas are dealt with in other topics.

One of the first steps in an enterprise application is creating the domain model, this entails listing the entities in the domain and defining the relationships between them. Domain modeling can be complex but the idea is simple, a domain model is a conceptual image of the problem you are trying to solve, a object in a domain model need not be a physical object but just a concept used by your system. A relationship is an imaginary link between objects that need to "know" about one another. So in short a domain model describes the objects and there relationship but not how a system acts on the objects.

Business rules are then implemented by the session beans and MDBs as discussed previously, while the persistence API implements the domain model that the business rules act on. UML diagrams and formal class diagrams are popular methods of creating domain models.

I am going to use the ActionBazaar application from the book to explain domain modeling, I will not detail all the code just enough to understand the concept, the application has a number of activities

We can pick out the domain objects by looking for the nouns: seller, item, category, bidder, bid and order

Looking at the two pictures above will help in placing the links (relationships) between the objects, thus creating the domain model. Although this is a simple example, this could takes days on a more complex example. We end up with a domain model looking like the one below

The domain model is formed of a number of one-to-one, one-to-many and many-to-many relationships between the objects. Lets explain in more detail what each means

Objects These are like Java objects, the can have behavior (methods) and state (instance variables), there could be hundreds of objects in a domain model.
Relationships This defines the relationship between one object and another, these relationships are indicated by the arrows in the above picture. A single arrow heads means that the relationship is unidirectional (one way) and having two arrow heads means the relationship is bi-directional. Words describing this are has, is part of, is member of, belongs to, etc
Multiplicity or Cardinality

this refers to the multifaceted nature of relationships

  • one-to-one - each side of the relationship may have at most only one object (person can have only one national insurance number and a national insurance number can be assigned only to one person)
  • one-to-many - a particular object instance may be related to multiple instances of another
  • many-to-many - both sides of the relationship can have more than one object
Ordinality or Optionality this determines whether an associated entity exists, the relationship may be optional, for an example a user many not have any bids for instance but he/she could have

The EJB 3 Java Persistence API (JPA) is a meta-data driven POJO technology, which means the objects do need to implement an interface, extend a class, or fit into any framework pattern, they are just plain old java objects. You use annotations or XML to give the persistence provider the following information

A standard POJO domain object in Java would look like something below

POJO domain object

public class Category {
  protected Long id;

  protected String name;
  protected Date modificationDate;

  protected Set<Item> items;
  protected Category parentCategory;
  protected Set<Category> subCategories;

  public Category() {}

  public Long getId() {
    return this.id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  // The rest of the setters and getters for each instance variable
  ...
}

Although the POJO above is a acceptable Java domain object, there are a number of problems

Entities Annotations

The @Entity property converts a POJO in to an entity, it marks the POJO as a domain object that can be uniquely identified, all entities must have a public or protected no-argument constructor, the constructor is used to create a new entity instance by using the new operator. Entities also support the full OO features such as inheritance and polymorphism.

Entity inheritance @Entity
public class User {
  ...
  String userId;
  String username;
  ...
}

@Entity class Seller extends User { ... }

The above example means that when the seller entity is persisted all the inherited fields are also persisted, be careful as the User entities could be saved on its own which may not be the desired affect, to prevent this you could make the User entity abstract, abstract entities cannot be instantiated or saved.

An entity maintains its state by using either fields or properties (via setter and getter methods), you cannot mix and match, so specify one of the other

field-based persistence @Entity
public class Category {

  @Id
  public long id;

  public String name;
  public Date modificationDate;

  public Category() {}
}

It is possible to stop a particular property from being persisted by marking the property (field-based) with the @Transient annotation or marking the getter in a property-based entity.

@Transient @Entity
public class Category {

  @Id
  public long id;

  public String name;
  public Date modificationDate;

  @Transient
  public Long userCount;

  public Category() {}
}

There are a number of data types that can be persisted

Types
Examples
Java Primitives int, double, long
Java Primitives wrappers java.lang.Integer, java.lang.Double
String Type java.lang.String
Java API serializable types java.math.BigInteger, java.sql.Date
User-defined serializable types class that implements java.io.Serializable
Array types byte[ ], char[ ]
Enumerated types {SELLER, BIDDER, CSR, ADMIN}
Collection of entity types Set<Category>
Embeddable class Classes that are defined @Embeddable

Every entity of the domain model must be uniquely identifiable, this is the same as using primary keys in a database each row is uniquely identified by is primary key, its also the same as in Java when using the equals to compare two different objects data. There are several ways of telling the persistence provider where the identity of an entity is stored.

@Id annotation this marks the field (apply to the variable) or property (apply to the get method) as the identity of an entity. There are limitations on what you can use EJB 3 supports primitives, primitive wrappers and Serialization types likes java.lang.String, java.util.Date and java.sql.Date. The one thing this annotation cannot do is use more than one field or property value to identify an entity, this is commonly know as a composite key, to accomplish this you can use the @IdClass and @Embedded annotations
@IdClass annotation This annotation allows you to use more than one @Id annotation in a sensible, there is a problem when using more than one field is how do you compare two instances in an automated fashion. I have an example below so take a look
@Embedded annotation

Using this annotation is like moving the @IdClass annotation right into your entity and using the identity fields nested inside it to store entity data.

Examples
@Id @Entity
public class Category {

  // Field
  @Id
  protected String name;

  // Property
  @Id
  public String getName() {
    return this.name;
  }
  ...
}
@IdClass

# CatgeoryPK class - this must be serialized
public class CategoryPK implements Serializable {
  String name;
  Date createDate;


  public CategoryPK() {}

  public boolean equals(Object other) {
    if (other instanceof Category) {
      final CategoryPK otherCategoryPK = (CategoryPK) other;
      return (otherCategoryPK.createDate.equals(name) &&
        otherCategoryPK.createDate.equals(createDate));
    }

    return false;
  }

  public int hashCode() {
    return super.hashCode();
  }
}

## The entity
@Entity
@IdClass(CategoryPK.class)
public class Category {
  public Category() {}

  @Id
  protect String name;


  @Id
  protected Date createDate;

  ...
}

@Embedded

# CatgeoryPK class - does not be serialized
@Embeddable
public class CategoryPK {
  String name;
  Date createDate;

  public CategoryPK() {}

  public boolean equals(Object other) {
    if (other instanceof Category) {
      final CategoryPK otherCategoryPK = (CategoryPK) other;
      return (otherCategoryPK.createDate.equals(name) &&
        otherCategoryPK.createDate.equals(createDate));
    }

    return false;
  }

  public int hashCode() {
    return super.hashCode();
  }
}

# Entity
@Entity
public class Category {
  public Category() {}

  // No name and createDate fields

  @EmbeddedId
  protected CategoryPK categoryPK;

  ...
}

The @Embeddable annotation is used to designate persistence objects that need not have an identity of their own, this is because they are identified by the entity objects that they are nested inside and never persisted or accessed on their own, for an example the address below is never accessed outside of using the User entity so there is no need for the address to have an identity of its own, this is what the @Embeddable annotation is used for.

@Embeddable @Embeddable
public class Address {
  protected String streetLine1;
  protected String streetLine2;
  protected String city;
  protected String state;
  protected String zip code;
  protected String country;
  ...
}

@Entity
public class User {
  @Id
  protected Long Id;
  protected String username;
  protected String first name;
  protected String last name;
  @Embedded
  protected String Address address;
  protected String email;
  protected String phone;
  ...
}

Entity Relationships

There are a number of relationships a entity can have, below is a table describing the relation types and the corresponding annotation

Relationship type
Annotation
One-to-One
@OneToOne
One-to-Many
@OneToMany
Many-to-One
@ManyToOne
Many-to-Many
@ManyToMany

The @OneToOne annotation is used to mark uni- or bidirectional one-to-one relationships, A unidirectional is pictured below

An example of this is

@OneToOne (unidirectional)

# Field-based
@Entity
public class User {
  @Id
  protected String userId;
  protected String email;
  @OneToOne
  protected BillingInfo billingInfo;

}

# Property-based
@Entity
public class User {
  @Id
  protected String userId;
  protected String email;
  ...
  @OneToOne
  public BillingInfo getbBilling() {
    return this.billing;
  }

}


@Entity
public class BillingInfo {
  @Id
  protected Long billingId;
  protected String creditCardType;
  ...
}

@OneToOne (bidirectional)

@Entity
public class User {
  @Id
  protected String userId;
  protected String email;
  @OneToOne
  protected BillingInfo billingInfo;

}


@Entity
public class BillingInfo {
  @Id
  protected Long billingId;
  protected String creditCardType;
  ...
  @OneToOne(mappedBy="billingInfo", optional=false);
  protected User user;

}

Note: The mappedBy tells the container the owning side of the relationship, the optional attribute tells the container that the billingInfo object cannot exist without a related User object

The definition of the @OneToOne annotation is below

@OneToOne definition @Target({METHOD,FIELD}) @Retention(RUNTIME)
public @interface OneToOne {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fetch() default EAGER;
  boolean optional() default true;
  String mappedBy() default "";
}

Notes:
Target - can use either property-based or field-based persistence
targetEntity - tells the persistence provider what the related entity class is (optional)
cascade - controls what happens to related data when the relationship is altered or deleted
fetch - specifies when and how the related fields are populated from the database tables
optional - tells the persistence provider if the related object must always be present
mappedBy - specifies the owning side of the relationship

The @OneToMany and @ManyToOne, in the relationship one of the entities will have two more more references of the other, this usually means that an entity has a collection-type-field such as a Set or List storing multiple instances of another entity. If the association between two entities is bidirectional, one side of the association is one-to-many and the opposite side of the association side of the association is many-to-one.

@OneToMany interface

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default();
  FetchType fetch() default LAZY;
  String mappedBy() default "";
}

Note:
targetEntity - used to specify the class related entity if it is not immediately obvious

@ManyToOne interface @Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default();
  FetchType fetch() default EAGER;
  boolean optional() default true;
}
Example @Entity
public class Item {
  @Id
  protected Long itemId;
  protected String title;
  ...
  @OneToMany(targetEntity=Bid.class,mappedBy="item")
  protected Set<Bid> bids;

  ...
}

@Entity
public class Bid {
  @Id
  protected Long bidId;
  ...
  @ManyToOne
  protected Item item;

  ...
}

The example above shows a bidirectional relationship, the @ManyToOne annotation on the item variable tells the persistence provider that more than one Bid entity could hold references to the same Item instance, for bidirectional one-to-many relationships ManyToOne is always the owning side of the relationship.

The @ManyToMany relationship means that both sides might have multiple references to related entities, these relationships can be either uni or bidirectional, the owning side is defined as the one with the mappedBy on the "subordinate" entity. The definition is the same as the OneToMany

@ManyToMany interface @Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToMany {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default();
  FetchType fetch() default LAZY;
  String mappedBy() default "";
}
Example @Entity
public class Category {
  @Id
  protected Long categoryId;
  protected String name;
  ...
  @ManyToMany
  protected Set<Item> items;

  ...
}

@Entity
public class Item {
  @Id
  protected Long itemId;
  protected String title;
  ...
  @ManyToMany(mappedBy="items")
  protected Set<Category> categories;

  ...
}
  

To summarize here is a table listing the elements that are available to each annotation

Element
@OneToOne
@OneToMany
@ManyToOne
@ManyToMany
targetEntity
Yes
Yes
Yes
Yes
cascade
Yes
Yes
Yes
Yes
fetch
Yes
Yes
Yes
Yes
optional
Yes
No
Yes
No
mappedBy
Yes
Yes
No
Yes

If you still find it hard to mapp the tables with the annotation here is what you are looking for in the table or when you create a table

many-to-one user_id int foreign key references users
one-to-one user_id int unique foreign key references users
billing_details_id int primary key foreign key references users

Note: notice the unique and primary key which means the column will contain a unique value
many-to-many

To reperesent a many-to-many association in a relational database you must introduce a new table called a link table

create table user_billing_details (
  user_id int foreign key references users,
  billing_details_id int foreign key references billing_details,
  primary key (user_id, billing_details_id)
)