An entity is a lightweight persistent domain object. Entity classes are also known as domain models. In a School ERP System, Student is a domain model or Entity class that can be managed by JPA. You will learn Entity class in JPA and what are the rules one has to follow in details in this tutorial.

You learned about the basics of JPA and Hibernate on the previous page. Let us understand where the Entity class fits in a typical Multilayered Java application.

A typical multilayered Java Application

In a multilayer java architecture, a domain model is accessed from every component. DAO will use it to manage data, the presentation may use it to convert it to a JSON payload and so on.

Domain model in a Multilayer architecture
Domain model in a Multilayer architecture

It is important to design Entity/domain models in a way that it does not depend on any orthogonal Java API. For example, the domain object should not perform database operations, JNDI lookup, etc.

Domain models (JPA Entities) are advised to be written as POJOs. POJO – Plain Old Java Object.

POJO terminology was coined by Martin Fowler, Rebecca Parsons, and Josh Mackenzie in 2000.

Rules for writing @Entity classes

  • Entity classes must be annotated with @Entity.
  • Must have a public/protected no-arg constructor, can have other constructors.
  • Entity classes must be a top-level class, enum or interface must not be designated as an entity.
  • Both abstract and concrete classes can be entities.
  • The entity class must not be final. No methods or persistent instance variables of the entity class may be final.
  • I advise making entity class implement Serializable, though this is not mandatory.
  • Every private/protected class properties should have Getter/Setter implemented.
@Entity
public class Attachment implements java.io.Serializable {...}
  • Entities support inheritance, polymorphic associations, and polymorphic queries.
  • Additional you can have JavaBean Validation annotations applied to @Entity classes.
@Entity
@Table(name = "departments")
public class Department implements java.io.Serializable {

    private Integer id;

    private SocialProfile socialProfile;

    private Institute institute;

    private String deptName;

    private String shortName;

    //Must have
    public Department() {
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

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

    @OneToOne
    public SocialProfile getSocialProfile() {
        return socialProfile;
    }

    public void setSocialProfile(SocialProfile socialProfile) {
        this.socialProfile = socialProfile;
    }

    @ManyToOne
    public Institute getInstitute() {
        return institute;
    }

    public void setInstitute(Institute institute) {
        this.institute = institute;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", Department.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("socialProfile=" + socialProfile)
                .add("institute=" + institute)
                .add("deptName='" + deptName + "'")
                .add("shortName='" + shortName + "'")
                .toString();
    }
}
public class Department {

    private Integer id;

    private SocialProfile socialProfile;

    private Institute institute;

    private String deptName;

    private String shortName;

    public Department() {
    }

    public Integer getId() {
        return id;
    }

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

    public SocialProfile getSocialProfile() {
        return socialProfile;
    }

    public void setSocialProfile(SocialProfile socialProfile) {
        this.socialProfile = socialProfile;
    }

    public Institute getInstitute() {
        return institute;
    }

    public void setInstitute(Institute institute) {
        this.institute = institute;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", Department.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("socialProfile=" + socialProfile)
                .add("institute=" + institute)
                .add("deptName='" + deptName + "'")
                .add("shortName='" + shortName + "'")
                .toString();
    }
}

Attributes of Persistent class (@Entity)

Attributes here means persistent fields and properties of the domain model (entity class). Properties that hold values are called states. I discourage using public states, rather make the fields private/protected and implement getter/setter for them.

1. Every Persistent property should have getter/setter

public class MyDomain implements Serializable {
  private T property;

  public MyDomain(){}

  public T getProperty(){return this.property;}

  public void setProperty(T prop){ this.property = prop; }
}

2. Use Collection interfaces, not concrete classes.

For  java.util.Collection fields, propertied must be defined to use one of the interfaces java.util.Collection, java.util.Set, java.util.List or java.util.Map based on use cases.

It is always a good practice to assign an empty collection to the property, so you don’t encounter NullPointerException, accidentally.

@Entity
@Table(name = "academic_terms")
public class AcademicTerm implements java.io.Serializable {

  // Good practice to assign an empty HashSet().
  private Set<Section> sections = new HashSet<Section>(0);
}

3. List of supported property types in JPA

The persistent fields an entity may be of the following types: Java primitive types & their wrapper class, java.lang.String, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, byte[], Byte[], char[], Character[], java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time.OffsetTime, java.time.OffsetDateTime, and user-defined types that implement the Serializable interface, enums, entity types, collections of entity types, embeddable classes, collections of basic and embeddable types.

Avoid using java.util.Date. Instead use the classes from java.time.*, such as java.time.LocalDate, java.time.LocalTime, and etc.

Entity metadata – using JPA annotations

Metadata means data about data. Entity metadata (Domain model metadata) is information about domain models.

This simply means, metadata has the information such as the db-table name where the data will be stored, the Column names, foreign key, Unique constraints and other details needed by the JPA to manage the domain objects.

There are basically 2 ways to specify these metadata:

  1. Using JPA annotations from javax.persistence.*
    You already used @Entity and @Table.
  2. Using XML descriptor files. This will not be covered in this course.

You will only learn to use JPA annotations, I don’t recommend separating it to XML descriptor files.

Maximum part of your JPA learning is to understand the metadata configurations correctly.

jstobigdata.com

For reference, keep the JPA API doc handy. Please share your feedback in the comments below.

By |Last Updated: August 24th, 2019|Categories: Hibernate, JPA|

Table of Contents