As you learned in the Basic Entity Mapping tutorial, every Entity class in JPA must be annotated with @Entity
and its id field should be annotated with @Id
. There are several other optional annotations available, they will be discussed as part of Entity Mapping. JPA annotations can be placed on fields and/or on properties (getter/setter). You will learn Access Type in details in this section.
Entities design should be fine-grained, meaning more classes than database tables.
Entity Mapping and POJO strategy in JPA
I will make use of a simple example to understand the strategy used in mapping entities in JPA.
In a school management system, there is a has-a relation between, Institute & SocialProfile, Department & SocialProfile, and Institute & Department. Each of these entities is also uniquely identified by id
field.
1. Understand Entity relationships.
Entities can have aggregations (has-a) and Inheritance. Consider this into consideration while creating POJO. In this example the Institute - Department
has 1 to N relationship (@OneToMany
). Institute – SocialProfile has 1 to 1 (@OneToOne
) relationship.
@Entity @Table(name = "institutes") public class Institute implements Serializable { @Id @GeneratedValue private Integer id; @OneToMany private Set<Department> departments = new HashSet<>(0); @OneToOne private SocialProfile socialProfile; ... }
@Entity @Table(name = "departments") public class Department implements Serializable { @Id @GeneratedValue private Long id = 0L; @OneToOne private SocialProfile socialProfile; @ManyToOne private Institute institute; ... }
@Entity @Table(name = "socialProfiles") public class SocialProfile implements Serializable { @Id @GeneratedValue private Long id = 0L; ... }
2. The identifier and generation strategy.
@Id
could be primitive (Long, Integer etc), non-primitive (String, BigDecimal) or composite types. There is also a strategy that decides how the value of the id
field is generated.
@Id @GeneratedValue private Long id = 0L;
3. Understand entity Lifecycle dependencies
If an institute
is deleted, the linked socialprofile
should be deleted as well. This is called cascading.
@Entity @Table(name = "institutes") public class Institute implements Serializable { ... @OneToOne(cascade = CascadeType.REMOVE) private SocialProfile socialProfile; ... }
4. Configuring table names.
With the help of @Table
on top of Entity class, you can specify the table name where the model objects will be stored. By default, JPA/Hibernate will pick the normalized name as class. e.g Institute model objects will be stored in institute table, but this is configurable with @Table
.
@Entity @Table(name = "institutes") public class Institute implements Serializable { ... }
Access Type in JPA
JPA provides 2 types of access types, field, and property access types. The placement of @Id
determines which strategy to be used. By default only a single strategy is followed.
If you put
@Id
on the field – Entity will beAccessType.FIELD
, if you put it on the getter – it will beAccessType.PROPERTY
.
Read the thread on StackOverflow to understand which one to use.
AccessTypes can be configured with the help of @Access
.
@Entity @Table(name = "institutes") @Access(AccessType.FIELD) public class Institute implements Serializable { ... }
@Entity @Access(AccessType.PROPERTY) public class Person { @Column("nickName") //Optional public String getNickName(){ if(this.name != null) { return this.generateNickName(this.name); } else return "John"; } }
In summary, understand the bigger picture of the entity. How it will be used in future requirements as well. This will help you design your Entities better.