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.


Setting up a Hibernate Project

This document outlines the steps involved in setting up a Hibernate project in Java, configuring your development environment, and configuring Hibernate using both XML and annotation-based approaches.

1. Project Setup

1.1. Creating a Java Project

Start by creating a new Java project in your IDE (e.g., IntelliJ IDEA, Eclipse, NetBeans). Select a suitable project type (e.g., Maven, Gradle, or a simple Java project). For more robust dependency management, Maven or Gradle are highly recommended.

1.2. Project Structure (Maven Example)

If you're using Maven, your project structure would typically look like this:

 my-hibernate-project/
    ├── src/
    │   ├── main/
    │   │   ├── java/
    │   │   │   └── com/example/
    │   │   │       └── model/   (Your entity classes)
    │   │   │       └── util/    (Hibernate configuration helper)
    │   │   └── resources/
    │   │       └── hibernate.cfg.xml (Hibernate configuration file)
    │   └── test/
    │       └── java/
    ├── pom.xml           (Maven project file) 

2. Configuring the Development Environment

2.1. Installing a Java Development Kit (JDK)

Ensure you have a JDK installed. Hibernate requires a compatible JDK version (typically JDK 8 or later). Verify your JDK installation by running java -version in your terminal.

2.2. Choosing an Integrated Development Environment (IDE)

Select an IDE for Java development. IntelliJ IDEA, Eclipse, and NetBeans are popular choices. Install the IDE and configure it to use your JDK.

2.3. Setting up a Database

Hibernate needs a database to interact with. Choose a database (e.g., MySQL, PostgreSQL, H2) and install the database server. Create a database and a user account with appropriate privileges for your Hibernate application.

3. Adding Dependencies

Your project needs the Hibernate core library and the JDBC driver for your chosen database. If using Maven, add the following dependencies to your pom.xml file:

 <dependencies>
        <!-- Hibernate Core -->
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.4.1.Final</version> <!-- Use the latest version -->
        </dependency>

        <!-- JDBC Driver for MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version> <!-- Use the latest version -->
        </dependency>

        <!-- (Optional) For logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>2.0.9</version> <!-- Or your preferred logging implementation -->
            <scope>runtime</scope>
        </dependency>
    </dependencies> 

Replace 8.0.33 and 6.4.1.Final with the latest versions available for the database driver and Hibernate core, respectively. If using a different database, change the MySQL driver dependency accordingly (e.g., for PostgreSQL use org.postgresql:postgresql).

4. Configuring Hibernate

Hibernate can be configured in two primary ways: using an XML configuration file (hibernate.cfg.xml) or using annotation-based configuration.

4.1. XML Configuration (hibernate.cfg.xml)

Create a file named hibernate.cfg.xml in your src/main/resources directory. This file contains the database connection details, Hibernate settings, and mappings to your entity classes.

 <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>
        <session-factory>
            <!-- Database connection settings -->
            <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
            <property name="connection.url">jdbc:mysql://localhost:3306/your_database_name</property>
            <property name="connection.username">your_username</property>
            <property name="connection.password">your_password</property>

            <!-- JDBC connection pool (use the built-in) -->
            <property name="connection.pool_size">10</property>

            <!-- SQL dialect -->
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

            <!-- Enable Hibernate's automatic session context management -->
            <property name="current_session_context_class">thread</property>

            <!-- Disable the second-level cache  -->
            <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

            <!-- Echo all executed SQL to stdout -->
            <property name="show_sql">true</property>

            <!-- Drop the schema and re-create it on startup -->
            <property name="hbm2ddl.auto">update</property>

            <!-- Mappings -->
            <mapping class="com.example.model.YourEntityClass"/>
            <!-- Add more mapping elements for each entity -->

        </session-factory>
    </hibernate-configuration> 
  • Replace com.mysql.cj.jdbc.Driver with the correct driver class for your database.
  • Replace jdbc:mysql://localhost:3306/your_database_name with the URL for your database.
  • Replace your_username and your_password with your database credentials.
  • Replace org.hibernate.dialect.MySQLDialect with the appropriate dialect for your database (e.g., org.hibernate.dialect.PostgreSQLDialect for PostgreSQL, org.hibernate.dialect.H2Dialect for H2).
  • Replace com.example.model.YourEntityClass with the fully qualified name of your entity class. Add a <mapping class="..."/> element for each entity you want Hibernate to manage.
  • hbm2ddl.auto: This property controls schema generation. update will update the schema if it exists or create it if it doesn't, but only adds new tables/columns, it won't remove anything. Other common options are create (drops and recreates the schema), create-drop (creates on startup, drops on shutdown), and validate (validates the schema against the mapping). Warning: Using `create` or `create-drop` can destroy your existing database! Use carefully, especially in production.

4.2. Annotation-Based Configuration

With annotation-based configuration, you annotate your entity classes with JPA annotations (@Entity, @Id, @GeneratedValue, etc.) and configure Hibernate programmatically.

First, annotate your entity class:

 package com.example.model;

    import jakarta.persistence.*;

    @Entity
    @Table(name = "your_table_name") // Optional, defaults to class name
    public class YourEntityClass {

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

        @Column(name = "your_column_name")
        private String yourProperty;

        // Getters and setters...
    } 

Then, create a utility class to build the SessionFactory:

 package com.example.util;

    import org.hibernate.SessionFactory;
    import org.hibernate.boot.MetadataSources;
    import org.hibernate.boot.registry.StandardServiceRegistry;
    import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

    public class HibernateUtil {

        private static SessionFactory sessionFactory;

        static {
            try {
                // A SessionFactory is set up once for an application!
                StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                        .configure() // configures settings from hibernate.cfg.xml
                        .build();
                try {
                    sessionFactory = new MetadataSources( registry )
                            .addAnnotatedClass(com.example.model.YourEntityClass.class) // Add your entity class
                            .buildMetadata()
                            .buildSessionFactory();
                }
                catch (Exception e) {
                    // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
                    // so destroy it manually.
                    StandardServiceRegistryBuilder.destroy( registry );
                    throw e;
                }
            }
            catch (Throwable ex) {
                // Make sure you log the exception, as it might be swallowed
                System.err.println("Initial SessionFactory creation failed." + ex);
                throw new ExceptionInInitializerError(ex);
            }
        }

        public static SessionFactory getSessionFactory() {
            return sessionFactory;
        }

        public static void shutdown() {
            if (sessionFactory != null) {
                sessionFactory.close();
            }
        }
    } 
  • Replace com.example.model.YourEntityClass.class with the class of your entity
  • In this example, `hibernate.cfg.xml` still handles the connection details, but you can further configure using annotations.
  • Alternatively, you can configure Hibernate entirely programmatically without `hibernate.cfg.xml`, but this is often more complex.

4.3. Using Hibernate

Here's a basic example of how to use the SessionFactory to interact with the database:

 import com.example.model.YourEntityClass;
    import com.example.util.HibernateUtil;
    import org.hibernate.Session;
    import org.hibernate.Transaction;

    public class Main {
        public static void main(String[] args) {
            try (Session session = HibernateUtil.getSessionFactory().openSession()) {
                Transaction transaction = null;
                try {
                    transaction = session.beginTransaction();

                    // Create a new instance of your entity
                    YourEntityClass entity = new YourEntityClass();
                    entity.setYourProperty("Some data");

                    // Save the entity
                    session.persist(entity);

                    transaction.commit();
                } catch (Exception e) {
                    if (transaction != null) {
                        transaction.rollback();
                    }
                    e.printStackTrace();
                }
            } finally {
                HibernateUtil.shutdown(); // Close the SessionFactory when done.
            }
        }
    }