Start here when the learner needs a working Hibernate project before Spring, validation, or advanced querying. The page should make persistence visible: entity, mapping, SessionFactory, Session, transaction, generated SQL.
The unique learner problem is setup confidence. A beginner should leave with one entity saved and read back, plus a clear sense of what each bootstrapping part does.
The first Hibernate project should be deliberately small. A single Product entity proves that dependencies, database connection, dialect, mapping, and transaction boundaries are correct.
Do not start with Spring, validation, many-to-many relationships, or caching. Those topics become easier after a plain CRUD path works.
Hibernate setup fails when learners copy files without knowing their job. The configuration file tells Hibernate how to connect and which mappings exist. SessionFactory stores that metadata. Session performs a unit of database work.
The first useful exercise is save, find, update, and delete for one entity. This gives practical feedback for every core Hibernate concept without distracting framework layers.
<dependencies>
<!-- Hibernate Core -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.4.0.Final</version>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.2.0</version>
</dependency>
<!-- C3P0 Connection Pool (optional) -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>6.4.0.Final</version>
</dependency>
</dependencies>
<?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 -->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydb?useSSL=false</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<!-- SQL Dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Show generated SQL -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- Schema management: validate | update | create | create-drop -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- Annotated entity classes -->
<mapping class="com.example.entity.User"/>
<mapping class="com.example.entity.Product"/>
<mapping class="com.example.entity.Order"/>
</session-factory>
</hibernate-configuration>
package com.example.entity;
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false, unique = true, length = 50)
private String username;
@Column(nullable = false)
private String email;
// No-arg constructor required by Hibernate
public User() {}
public User(String username, String email) {
this.username = username;
this.email = email;
}
// Getters and setters
public Long getId() { return id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override
public String toString() {
return "User{id=" + id + ", username='" + username + "', email='" + email + "'}";
}
}
package com.example.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Load hibernate.cfg.xml from classpath
sessionFactory = new Configuration()
.configure("hibernate.cfg.xml")
.buildSessionFactory();
} catch (Exception e) {
System.err.println("SessionFactory creation failed: " + e);
throw new ExceptionInInitializerError(e);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
getSessionFactory().close();
}
}
package com.example;
import com.example.entity.User;
import com.example.util.HibernateUtil;
import org.hibernate.*;
public class Main {
public static void main(String[] args) {
// Save a user
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
User user = new User("alice", "alice@example.com");
session.persist(user); // INSERT INTO users ...
tx.commit();
session.close();
System.out.println("Saved: " + user);
// Retrieve the user
session = HibernateUtil.getSessionFactory().openSession();
User found = session.get(User.class, user.getId());
System.out.println("Found: " + found);
session.close();
HibernateUtil.shutdown();
}
}
try (Session session = sessionFactory.openSession()) {
Transaction tx = session.beginTransaction();
Product p = new Product("Keyboard", new BigDecimal("89.99"));
session.persist(p);
tx.commit();
}
// Then open a new Session and use session.find(Product.class, id).
Building a SessionFactory parses mappings, prepares services, and initializes connection management, so it is expensive and thread-safe by design. Create one for the application or persistence unit, then open short-lived Sessions from it.
Hibernate only creates schema objects when the configured schema-generation strategy allows it. If hbm2ddl.auto is validate or none, the table must already exist and match the entity mapping.
Commit or roll back the Transaction, then close the Session. Keep the SessionFactory open until application shutdown.
Explore 500+ free tutorials across 20+ languages and frameworks.