Performing Basic CRUD with Hibernate: A Complete Guide

Illustration for Performing Basic CRUD with Hibernate: A Complete Guide
By Last updated:

In any database-driven application, CRUD (Create, Read, Update, Delete) operations are at the core. Hibernate, a powerful Object-Relational Mapping (ORM) framework in Java, makes CRUD simple and efficient by allowing developers to work directly with Java objects instead of raw SQL queries.

This tutorial will guide you step-by-step through performing basic CRUD with Hibernate, complete with entity mapping, configuration, CRUD code examples, and best practices for production-ready applications.


Setup and Configuration

Maven Dependency

<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>6.4.1.Final</version>
</dependency>

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"/>
  </session-factory>
</hibernate-configuration>

Entity Class

import jakarta.persistence.*;

@Entity
@Table(name = "students")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "student_name", nullable = false)
    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
}

Hibernate Utility Class (SessionFactory)

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory;

    static {
        try {
            sessionFactory = new Configuration()
                    .configure("hibernate.cfg.xml")
                    .addAnnotatedClass(Student.class)
                    .buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

CRUD Operations with Hibernate

Create (Insert)

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();

Student student = new Student("Alice", 22);
session.persist(student);

tx.commit();
session.close();

✅ Hibernate generates the INSERT statement automatically.


Read (Select)

Session session = HibernateUtil.getSessionFactory().openSession();

Student student = session.get(Student.class, 1L);
System.out.println(student.getName() + " - " + student.getAge());

session.close();

✅ Uses the primary key to fetch an entity.


Update

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();

Student student = session.get(Student.class, 1L);
student.setName("Updated Alice");
student.setAge(23);
session.update(student);

tx.commit();
session.close();

✅ Hibernate generates an UPDATE statement.


Delete

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();

Student student = session.get(Student.class, 1L);
session.remove(student);

tx.commit();
session.close();

✅ Hibernate generates a DELETE statement.


Querying Data

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> results = session.createQuery(cq).getResultList();

Native SQL Example

List<Object[]> results = session.createNativeQuery("SELECT * FROM students").list();

Caching and Performance Considerations

  • First-Level Cache → Session-specific, automatic.
  • Second-Level Cache → Application-wide, requires providers like EHCache.
  • Lazy Loading (default) → Data fetched only when needed.
  • Eager Loading → Fetches immediately.

Analogy:

  • Lazy loading = ordering food only when hungry.
  • Caching = remembering your previous order instead of asking the kitchen again.

Real-World Integration with Spring Boot

Spring Boot simplifies Hibernate CRUD with 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 to close sessions → memory leaks.
  • Using eager fetching everywhere → performance issues.
  • Misconfigured cascades → unintended deletes.
  • Using IDENTITY strategy with batch inserts → performance bottlenecks.

Best Practices

  • Always wrap operations in transactions.
  • Close sessions after use.
  • Use lazy fetching by default.
  • DTOs for APIs instead of exposing entities.
  • Enable batch operations and tune caching.

📌 Hibernate Version Notes

Hibernate 5.x

  • Relies on javax.persistence.
  • Classic SessionFactory and legacy APIs.

Hibernate 6.x

  • Uses jakarta.persistence.
  • Enhanced query APIs.
  • Improved SQL integration.

Conclusion and Key Takeaways

  • CRUD is the foundation of database interaction.
  • Hibernate simplifies CRUD with Sessions, Transactions, and mappings.
  • Queries can be performed via HQL, Criteria API, or native SQL.
  • Caching and lazy loading improve performance.
  • Hibernate integrates seamlessly with Spring Boot and JPA.

FAQ: Expert Hibernate Questions

  1. What’s the difference between Hibernate and JPA?
    JPA is a specification; Hibernate is a powerful implementation.

  2. How does Hibernate caching improve performance?
    By reducing redundant database queries.

  3. What are the drawbacks of eager fetching?
    It loads unnecessary data, consuming resources.

  4. How do I solve the N+1 select problem?
    Use JOIN FETCH or batch fetching.

  5. Can I use Hibernate without Spring?
    Yes, Hibernate works standalone.

  6. What’s the best inheritance mapping strategy?
    JOINED for normalization, SINGLE_TABLE for speed.

  7. How does Hibernate handle composite keys?
    With @EmbeddedId or @IdClass.

  8. How is Hibernate 6 different from Hibernate 5?
    Hibernate 6 uses jakarta.persistence and enhances query APIs.

  9. Is Hibernate suitable for microservices?
    Yes, but keep entities lightweight and use DTOs.

  10. When should I not use Hibernate?
    For raw SQL-heavy analytics or high-performance batch jobs.