📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.
🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.
▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube
Table of contents
- Defining a JPA Entity Class
- Requirements for Entity Classes
- Persistent Fields and Properties in Entity Classes
- Persistent Fields
- Persistent Properties
- Using Collections in Entity Fields and Properties
- Primary Keys in Entities
- Relationship Mapping
- Cascade Operations and Relationships
- Orphan Removal in Relationships
- Embeddable Classes in Entities
1. Defining a JPA Entity Class
An entity is a lightweight persistence domain object. Typically, an entity represents a table in a relational database, and each entity instance corresponds to a row in that table. The primary programming artifact of an entity is the entity class, although entities can use helper classes.The Point Entity Class Example
@Entity
public class Point {
// Persistent Fields:
private int x;
private int y;
// Constructor:
Point (int x, int y) {
this.x = x;
this.y = y;
}
// Accessor Methods:
public int getX() { return this.x; }
public int getY() { return this.y; }
// String Representation:
@Override
public String toString() {
return String.format("(%d, %d)", this.x, this.y);
}
}
2. Requirements for Entity Classes
- The class must be annotated with the jakarta.persistence.Entity annotation.
- The class must have a public or protected, no-argument constructor. The class may have other constructors.
- The class must not be declared final. No methods or persistent instance variables must be declared final.
- If an entity instance is passed by value as a detached object, such as through a session bean's remote business interface, the class must implement the Serializable interface.
- Entities may extend both entity and non-entity classes, and non-entity classes may extend entity classes.
- Persistent instance variables must be declared private, protected, or package-private and can be accessed directly only by the entity class's methods. Clients must access the entity's state through accessor or business methods.
3. Persistent Fields and Properties in Entity Classes
- java.lang.String
- Other serializable types, including:
- Wrappers of Java primitive types
- java.math.BigInteger
- java.math.BigDecimal
- java.util.Date
- java.util.Calendar
- java.sql.Date
- java.sql.Time
- java.sql.TimeStamp
- User-defined serializable types
- byte[]
- Byte[]
- char[]
- Character[]
- Other entities and/or collections of entities
4. Persistent Fields
- @Id - Identifies the unique ID of the database entry
- @GeneratedValue - Together with an ID this annotation defines that this value is generated automatically.
- @Transient - Field will not be saved in a database
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "first_name")
private String firstName;
@Transient // Field will not be saved in a database
private String lastName;
// getter and setter methods
}
5. Persistent Properties
@Entity
@Table(name = "student")
public class Student {
private int id;
private String firstName;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "first_name")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
6. Using Collections in Entity Fields and Properties
- java.util.Collection
- java.util.Set
- java.util.List
- java.util.Map
@ManyToMany(mappedBy = "projects", cascade = { CascadeType.ALL }) private Set<Employee> employees = new HashSet<Employee>();
@OneToMany(mappedBy = "instructor", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH }) private List<Course> courses;
7. Primary Keys in Entities
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "first_name")
private String firstName;
// getter and setter methods
}
@Embeddable
public class EmployeePK implements Serializable {
private String name;
private long id;
public EmployeePK() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
@Entity
public class Employee implements Serializable {
EmployeePK primaryKey;
public Employee() {
}
@EmbeddedId
public EmployeePK getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(EmployeePK pk) {
primaryKey = pk;
}
...
}
@Entity @IdClass(ProjectId.class)
public class Project {
@Id int departmentId;
@Id long projectId;
:
}
Class ProjectId {
int departmentId;
long projectId;
}
- Java primitive types
- Java primitive wrapper types
- java.lang.String
- java.util.Date (the temporal type should be DATE)
- java.sql.Date
- java.math.BigDecimal
- java.math.BigInteger
- The access control modifier of the class must be public.
- The properties of the primary key class must be public or protected if property-based access is used.
- The class must have a public default constructor.
- The class must implement the hashCode() and equals(Object other) methods.
- The class must be serializable.
- A composite primary key must be represented and mapped to multiple fields or properties of the entity class or must be represented and mapped as an embeddable class.
- If the class is mapped to multiple fields or properties of the entity class, the names and types of the primary key fields or properties in the primary key class must match those of the entity class.
8. Relationship Mapping
- @OneToOne
- @OneToMany
- @ManyToOne
- @ManyToMany
9. Cascade Operations and Relationships
- DETACH - If the parent entity is detached from the persistence context, the related entity will also be detached.
- MERGE - If the parent entity is merged into the persistence context, the related entity will also be merged.
- PERSIST - If the parent entity is persisted into the persistence context, the related entity will also be persisted.
- REFRESH - If the parent entity is refreshed in the current persistence context, the related entity will also be refreshed.
- REMOVE - If the parent entity is removed from the current persistence context, the related entity will also be removed.
@OneToMany(cascade=REMOVE, mappedBy="customer")
public Set<CustomerOrder> getOrders() { return orders; }
Read more at Guide to JPA and Hibernate Cascade Types
10. Orphan Removal in Relationships
@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<CustomerOrder> getOrders() { ... }
11. Embeddable Classes in Entities
package net.javaguides.hibernate.entity;
import jakarta.persistence.Embeddable;
@Embeddable
public class Address {
private String addressLine1;
private String addressLine2;
private String city;
private String state;
private String country;
private String zipCode;
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
}
import jakarta.persistence.*;
/**
* Created by ramesh
*/
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Embedded
private Name name;
private String email;
@Embedded
@AttributeOverrides(value = {
@AttributeOverride(name = "addressLine1", column = @Column(name = "house_number")),
@AttributeOverride(name = "addressLine2", column = @Column(name = "street"))
})
private Address address;
public User() {
}
public User(Name name, String email, Address address) {
this.name = name;
this.email = email;
this.address = address;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
What's Next?
Check out complete example at Hibernate Component Mapping Using @Embeddable and @Embedded Annotation.
firstName field is written two times . I guess third field is lastName which is transient
ReplyDelete@Column(name = "first_name")
private String firstName;
@Transient // Field will not be saved in a database
private String firstName;
// getter and setter methods