CRUD Operations with Hibernate (Create, Read, Update, Delete)
This is a hands-on lesson demonstrating how to perform basic CRUD operations using Hibernate. You'll learn how to save new objects to the database (Create), retrieve objects (Read), modify existing objects (Update), and delete objects (Delete) using Hibernate's API.
Hibernate Entity Mapping Explained
Defining Entities and Mapping
In Hibernate, an Entity represents a table in your database. Mapping defines how your Java classes (Entities) relate to the database tables and their columns. This process involves specifying which class represents which table, and which fields within the class represent which columns in the table. Annotations are a common and convenient way to achieve this mapping in Java.
Hibernate uses this mapping information to:
- Automatically create database schema (if configured to do so).
- Translate Java objects into database rows (and vice versa).
- Construct SQL queries based on your object-oriented model.
Creating Java Classes and Mapping with Annotations
Here's how you can create Java classes (Entities) to represent database tables and use annotations to map them using Hibernate:
Example: Product
Entity
Consider a database table named products
with columns: id
, name
, description
, and price
.
import javax.persistence.*;
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name", nullable = false, length = 255)
private String name;
@Column(name = "description", columnDefinition = "TEXT")
private String description;
@Column(name = "price", precision = 10, scale = 2)
private Double price;
// Constructors, Getters, and Setters (omitted for brevity)
public Product() {} // Important: A no-argument constructor is required by Hibernate.
public Product(String name, String description, Double price) {
this.name = name;
this.description = description;
this.price = price;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
Explanation of Annotations:
@Entity
: Marks the class as a JPA (Java Persistence API) entity. This tells Hibernate that this class represents a table in the database.@Table(name = "products")
: Specifies the name of the database table to which this entity is mapped. If omitted, Hibernate will assume the table name is the same as the class name (Product
). It's good practice to explicitly define the table name.@Id
: Marks theid
field as the primary key of the table.@GeneratedValue(strategy = GenerationType.IDENTITY)
: Specifies how the primary key value is generated.GenerationType.IDENTITY
indicates that the database will auto-generate the primary key (e.g., using an auto-increment column). Other strategies includeAUTO
,SEQUENCE
, andTABLE
.@Column(name = "name", nullable = false, length = 255)
: Maps thename
field to thename
column in the table.name
: Specifies the column name. If omitted, Hibernate uses the field name.nullable = false
: Indicates that the column cannot be null in the database.length = 255
: Specifies the maximum length of the column.
@Column(name = "description", columnDefinition = "TEXT")
: Maps thedescription
field to thedescription
column.columnDefinition = "TEXT"
: Allows you to define the specific data type of the column. In this case, it's defined asTEXT
, which is suitable for storing longer text.
@Column(name = "price", precision = 10, scale = 2)
: Maps theprice
field to theprice
column.precision = 10
: Defines the total number of digits allowed for the price.scale = 2
: Defines the number of digits after the decimal point.
Important Considerations:
- Getters and Setters: Hibernate requires getter and setter methods for all persistent fields (fields mapped to database columns).
- No-Argument Constructor: Hibernate also requires a no-argument (default) constructor for each entity class. This is used for creating instances during data retrieval.
- Data Types: Choose appropriate Java data types for your fields to match the corresponding database column types.
- Relationships: For representing relationships between tables (e.g., one-to-many, many-to-one), use annotations like
@OneToMany
,@ManyToOne
,@ManyToMany
. - Cascade Types: Understand CascadeTypes (e.g.,
CascadeType.ALL
,CascadeType.PERSIST
,CascadeType.REMOVE
) which control how operations on a parent entity affect related child entities. - Lazy Loading: Consider lazy loading (
FetchType.LAZY
) for relationships to improve performance, especially when dealing with large datasets.