Persistence top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

If you have a few years of experience in the Java ecosystem, and you're interested in sharing that experience with the community (and getting paid for your work of course), have a look at the "Write for Us" page. Cheers. Eugen

1. Introduction

In this tutorial, we’ll learn about the basics of entities along with various annotations that define and customize an entity in JPA.

2. Entity

Entities in JPA are nothing but POJOs representing data that can be persisted to the database. An entity represents a table stored in a database. Every instance of an entity represents a row in the table.

2.1. The Entity Annotation

Let’s say we have a POJO called Student which represents the data of a student and we would like to store it in the database.

public class Student {
    
    // fields, getters and setters
    
}

In order to do this, we should define an entity so that JPA is aware of it.

So let’s define it by making use of the @Entity annotation. We must specify this annotation at the class level. We must also ensure that the entity has a no-arg constructor and a primary key: 

@Entity
public class Student {
    
    // fields, getters and setters
    
}

The entity name defaults to the name of the class. We can change its name using the name element.

@Entity(name="student")
public class Student {
    
    // fields, getters and setters
    
}

Because various JPA implementations will try subclassing our entity in order to provide their functionality, entity classes must not be declared final.

2.2. The Id Annotation

Each JPA entity must have a primary key which uniquely identifies it. The @Id annotation defines the primary key. We can generate the identifiers in different ways which are specified by the @GeneratedValue annotation.

We can choose from four id generation strategies with the strategy element. The value can be AUTO, TABLE, SEQUENCE, or IDENTITY.

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    private String name;
    
    // getters and setters
}

If we specify GenerationType.AUTO, the JPA provider will use any strategy it wants to generate the identifiers.

If we annotate the entity’s fields, the JPA provider will use these fields to get and set the entity’s state. In addition to Field Access, we can also do Property Access or Mixed Access, which enables us to use both Field and Property access in the same entity.

2.3. The Table Annotation

In most cases, the name of the table in the database and the name of the entity will not be the same.

In these cases, we can specify the table name using the @Table annotation:

@Entity
@Table(name="STUDENT")
public class Student {
    
    // fields, getters and setters
    
}

We can also mention the schema using the schema element:

@Entity
@Table(name="STUDENT", schema="SCHOOL")
public class Student {
    
    // fields, getters and setters
    
}

Schema name helps to distinguish one set of tables from another,

If we do not use the @Table annotation, the name of the entity will be considered the name of the table.

2.4. The Column Annotation

Just like the @Table annotation, we can use the @Column annotation to mention the details of a column in the table.

The @Column annotation has many elements such as name, length, nullable, and unique.

@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    @Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
    private String name;
    
    // other fields, getters and setters
}

The name element specifies the name of the column in the table. The length element specifies its length. The nullable element specifies whether the column is nullable or not, and the unique element specifies whether the column is unique.

If we don’t specify this annotation, the name of the field will be considered the name of the column in the table.

2.5. The Transient Annotation

Sometimes, we may want to make a field non-persistent. We can use the @Transient annotation to do so. It specifies that the field will not be persisted.

For instance, we can calculate the age of a student from the date of birth.

So let’s annotate the field age with the @Transient annotation:

@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    @Column(name="STUDENT_NAME", length=50, nullable=false)
    private String name;
    
    @Transient
    private Integer age;
    
    // other fields, getters and setters
}

As a result, the field age will not be persisted to the table.

2.6. The Temporal Annotation

In some cases, we may have to save temporal values in our table.

For this, we have the @Temporal annotation:

@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    @Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
    private String name;
    
    @Transient
    private Integer age;
    
    @Temporal(TemporalType.DATE)
    private Date birthDate;
    
    // other fields, getters and setters
}

However, with JPA 2.2, we also have support for java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time.OffsetTime and java.time.OffsetDateTime.

2.7. The Enumerated Annotation

Sometimes, we may want to persist a Java enum type.

We can use the @Enumerated annotation to specify whether the enum should be persisted by name or by ordinal (default).

public enum Gender {
    MALE, 
    FEMALE
}
@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    @Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
    private String name;
    
    @Transient
    private Integer age;
    
    @Temporal(TemporalType.DATE)
    private Date birthDate;
    
    @Enumerated(EnumType.STRING)
    private Gender gender;
    
    // other fields, getters and setters
}

Actually, we don’t have to specify the @Enumerated annotation at all if we are going to persist the Gender by the enum‘s ordinal.

However, to persist the Gender by enum name, we’ve configured the annotation with EnumType.STRING.

3. Conclusion

In this article, we learned what JPA entities are and how to create them. We also learned about the different annotations that can be used to customize the entity further.

The complete code for this article can be found over on Github.

Persistence bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE