When working with Hibernate, the first step in interacting with the database is mapping Java classes to relational database tables. Hibernate achieves this through annotations like @Entity, @Table, and @Id. These annotations form the foundation of Object-Relational Mapping (ORM) in Hibernate.
In this tutorial, we’ll explore how to use these annotations effectively, dive into real-world examples, and build CRUD operations. By the end, you’ll understand how entity mapping simplifies database operations, improves maintainability, and integrates seamlessly with frameworks like Spring Boot.
What is an Entity in Hibernate?
An Entity in Hibernate represents a table in a database. Each entity instance corresponds to a row in that table.
@Entity
→ Marks the class as a persistent entity.@Table
→ Maps the entity to a specific table (optional if class name matches).@Id
→ Defines the primary key.
Think of it this way:
- Entity Class = Table
- Entity Instance = Table Row
Example: Basic Entity Mapping
import jakarta.persistence.*;
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "student_name", nullable = false, length = 100)
private String name;
@Column(name = "age")
private int age;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// Getters and setters
}
Explanation
@Entity
: MarksStudent
as an entity class.@Table(name = "students")
: Maps class to tablestudents
.@Id
: Marksid
as primary key.@GeneratedValue
: Defines how IDs are generated (AUTO, IDENTITY, SEQUENCE).@Column
: Maps class fields to table columns.
Relationships in Entity Mapping
Hibernate makes it easy to define relationships between entities.
One-to-Many Example
@Entity
@Table(name = "courses")
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@OneToMany(mappedBy = "course", cascade = CascadeType.ALL)
private List<Student> students = new ArrayList<>();
}
Many-to-One Example
@ManyToOne
@JoinColumn(name = "course_id")
private Course course;
Hibernate Configuration (hibernate.cfg.xml)
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/testdb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.example.Student"/>
<mapping class="com.example.Course"/>
</session-factory>
</hibernate-configuration>
CRUD Operations with Entities
Create
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Student student = new Student("Alice", 22);
session.persist(student);
tx.commit();
session.close();
Read
Session session = HibernateUtil.getSessionFactory().openSession();
Student student = session.get(Student.class, 1L);
System.out.println(student.getName());
session.close();
Update
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Student student = session.get(Student.class, 1L);
student.setName("Updated Name");
session.update(student);
tx.commit();
session.close();
Delete
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Student student = session.get(Student.class, 1L);
session.remove(student);
tx.commit();
session.close();
Querying with Entities
HQL Example
List<Student> students = session.createQuery("FROM Student WHERE age > :age", Student.class)
.setParameter("age", 20)
.list();
Criteria API Example
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Student> cq = cb.createQuery(Student.class);
Root<Student> root = cq.from(Student.class);
cq.select(root).where(cb.greaterThan(root.get("age"), 20));
List<Student> students = session.createQuery(cq).getResultList();
Caching and Performance Considerations
- Lazy Loading (default) → Fetch associations only when accessed.
- Eager Loading → Fetch associations immediately.
- First-Level Cache → Session-specific cache.
- Second-Level Cache → Application-wide, enabled via SessionFactory.
Analogy:
- Lazy loading = ordering food when you’re hungry.
- Caching = reusing already fetched data instead of going back to the database.
Real-World Integration with Spring Boot
Spring Boot simplifies Hibernate setup using Spring Data JPA:
spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
Repository Example:
public interface StudentRepository extends JpaRepository<Student, Long> {}
Common Pitfalls
- Forgetting
@Id
→ Hibernate won’t recognize the entity. - Using eager fetching everywhere → performance issues.
- Incorrect
cascade
setup → can lead to unintended deletes.
Best Practices
- Always define a primary key with
@Id
. - Use lazy fetching by default.
- Use DTOs for API responses.
- Keep entities lean and avoid business logic inside them.
📌 Hibernate Version Notes
Hibernate 5.x
- Relies on
javax.persistence
. - Legacy APIs for configuration and criteria.
Hibernate 6.x
- Migrated to
jakarta.persistence
. - Enhanced query API and SQL support.
- Better bootstrap and metadata handling.
Conclusion and Key Takeaways
- @Entity, @Table, and @Id form the backbone of Hibernate ORM.
- Entities map Java classes to database tables, enabling seamless CRUD operations.
- Relationships like One-to-Many and Many-to-One are handled via annotations.
- Hibernate integrates seamlessly with Spring Boot and JPA.
- Always follow best practices for fetching and cascading to avoid pitfalls.
FAQ: Expert Hibernate Questions
-
What’s the difference between Hibernate and JPA?
JPA is a specification, while Hibernate is a popular implementation. -
How does Hibernate caching improve performance?
By reducing database trips using first and second-level caches. -
What are the drawbacks of eager fetching?
Loads unnecessary data upfront, slowing performance. -
How do I solve the N+1 select problem?
UseJOIN FETCH
, batch fetching, or entity graphs. -
Can I use Hibernate without Spring?
Yes, Hibernate can run standalone. -
What’s the best inheritance mapping strategy?
JOINED
for normalization,SINGLE_TABLE
for speed. -
How does Hibernate handle composite keys?
With@EmbeddedId
or@IdClass
. -
How is Hibernate 6 different from Hibernate 5?
Hibernate 6 usesjakarta.persistence
, with enhanced SQL APIs. -
Is Hibernate suitable for microservices?
Yes, but prefer DTOs and stateless design. -
When should I not use Hibernate?
Avoid in raw SQL-heavy analytics or batch processing apps.