Hibernate 框架从入门到实战:全自动化 ORM 的力量 🔮
Hibernate 是 Java 领域最经典的全自动 ORM(对象关系映射)框架之一,它让开发者彻底告别繁琐的 JDBC 代码,通过对象操作数据库。本文将系统讲解 Hibernate 的核心概念、映射配置、 CRUD 操作、事务管理、HQL 查询语言以及与 Spring 的集成,帮助你全面掌握这门传统但依然重要的持久层技术!💪
📚 目录导航
一、Hibernate 概述:什么是 ORM? 1.1 从 JDBC 到 ORM 的进化 在 JDBC 时代,我们操作数据库是这样的:
flowchart LR
A["☕️ Java 对象"] -->|"手动映射"| B["📝 SQL 语句"]
B -->|"JDBC 执行"| C["🗄️ 数据库表"]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#f8bbd0
❌ 需要手动编写 SQL 语句
❌ 需要手动从 ResultSet 映射到 Java 对象
❌ 需要手动管理数据库连接和资源
❌ SQL 语句散落在代码各处,难以维护
而 ORM 的目标是:让对象和表之间自动映射,你只需要操作对象即可。
1.2 Hibernate 是什么? Hibernate 是一个全自动的 ORM 框架,它实现了 Java 对象与数据库表之间的自动映射:
flowchart LR
A["🧍 User 对象"] -->|"save()/update()"| B["📦 Hibernate ORM"]
B -->|"自动转换"| C["🗄️ users 表"]
A -->|"findById()"| B
B -->|"自动映射"| C
style A fill:#c8e6c9
style B fill:#e3f2fd
style C fill:#f8bbd0
Hibernate 的核心优势 :
✅ 全自动映射 :Java 对象 ↔ 数据库表,自动转换
✅ 无需编写 SQL :框架自动生成并执行 SQL
✅ 数据库无关性 :切换数据库只需修改配置
✅ 缓存支持 :内置一级缓存和二级缓存,提升性能
✅ 事务管理 :提供声明式事务支持
✅ 丰富查询 :HQL、QBC、原生 SQL 等多种查询方式
1.3 Hibernate vs MyBatis 对比
对比维度
Hibernate
MyBatis
映射方式
全自动
半自动
SQL 控制
框架自动生成
手动编写
学习曲线
较陡峭
平缓
灵活性
较低(但足够大多数场景)
高(完全可控)
性能调优
需要深入理解框架
直接优化 SQL
适用场景
业务简单、表结构稳定
复杂查询、性能敏感
国内市场
逐渐减少
绝对主流(+ MyBatis-Plus)
💡 国内现状 :MyBatis 因其灵活性和可控性在国内占据主流,但 Hibernate 在企业级应用中仍有广泛应用,特别是在传统行业(如金融、银行)中。选择框架需要根据项目实际需求决定,两者都是值得掌握的技能。
二、环境搭建与配置 2.1 Maven 依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 <project > <modelVersion > 4.0.0</modelVersion > <groupId > com.example</groupId > <artifactId > hibernate-demo</artifactId > <version > 1.0-SNAPSHOT</version > <properties > <hibernate.version > 6.3.1.Final</hibernate.version > <mysql.version > 8.0.33</mysql.version > </properties > <dependencies > <dependency > <groupId > org.hibernate</groupId > <artifactId > hibernate-core</artifactId > <version > ${hibernate.version}</version > </dependency > <dependency > <groupId > jakarta.persistence</groupId > <artifactId > jakarta.persistence-api</artifactId > <version > 3.1.0</version > </dependency > <dependency > <groupId > com.mysql</groupId > <artifactId > mysql-connector-j</artifactId > <version > ${mysql.version}</version > </dependency > <dependency > <groupId > com.zaxxer</groupId > <artifactId > HikariCP</artifactId > <version > 5.0.1</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > <scope > test</scope > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.30</version > <scope > provided</scope > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > <version > 2.0.9</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-simple</artifactId > <version > 2.0.9</version > </dependency > </dependencies > </project >
2.2 创建数据库表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 CREATE DATABASE IF NOT EXISTS hibernate_demo DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_unicode_ci;USE hibernate_demo; CREATE TABLE users ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR (50 ) NOT NULL UNIQUE , password VARCHAR (255 ) NOT NULL , email VARCHAR (100 ), status INT DEFAULT 1 , created_at DATETIME DEFAULT CURRENT_TIMESTAMP , updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4; CREATE TABLE articles ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL , title VARCHAR (200 ) NOT NULL , content TEXT, views INT DEFAULT 0 , created_at DATETIME DEFAULT CURRENT_TIMESTAMP , updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP , FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4; INSERT INTO users (username, password, email) VALUES ('admin' , 'pass123' , 'admin@example.com' ), ('test' , 'pass456' , 'test@example.com' ); INSERT INTO articles (user_id, title, content, views) VALUES (1 , 'Hibernate 入门' , 'Hibernate 是一个优秀的 ORM 框架...' , 100 ), (1 , 'Hibernate 进阶' , '本文讲解 Hibernate 的高级特性...' , 200 ), (2 , 'JPA 规范简介' , 'JPA 是 Java 持久化 API 规范...' , 150 );
2.3 hibernate.cfg.xml 全局配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.org/dtd/hibernate-configuration-3.0.dtd" > <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/hibernate_demo?useSSL=false& serverTimezone=Asia/Shanghai& characterEncoding=utf8 </property > <property name ="hibernate.connection.username" > root</property > <property name ="hibernate.connection.password" > your_password</property > <property name ="hibernate.connection.pool_size" > 10</property > <property name ="hibernate.connection HikariCP minimum-idle" > 5</property > <property name ="hibernate.connection HikariCP maximum-pool-size" > 20</property > <property name ="hibernate.dialect" > org.hibernate.dialect.MySQLDialect</property > <property name ="hibernate.show_sql" > true</property > <property name ="hibernate.format_sql" > true</property > <property name ="hibernate.hbm2ddl.auto" > update</property > <property name ="hibernate.transaction.factory_class" > org.hibernate.transaction.JDBCTransactionFactory </property > <property name ="hibernate.cache.use_second_level_cache" > true</property > <property name ="hibernate.cache.region.factory_class" > org.hibernate.cache.ehcache.internal.EhcacheRegionFactory </property > <property name ="hibernate.current_session_context_class" > thread</property > <mapping resource ="com/example/entity/User.hbm.xml" /> <mapping resource ="com/example/entity/Article.hbm.xml" /> </session-factory > </hibernate-configuration >
2.4 HibernateUtil 工具类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.example.util;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { Configuration configuration = new Configuration (); configuration.configure("hibernate.cfg.xml" ); sessionFactory = configuration.buildSessionFactory(); System.out.println("✅ SessionFactory 初始化成功" ); } catch (Exception e) { throw new RuntimeException ("初始化 SessionFactory 失败" , e); } } public static SessionFactory getSessionFactory () { return sessionFactory; } public static Session openSession () { return sessionFactory.openSession(); } public static Session getCurrentSession () { return sessionFactory.getCurrentSession(); } public static void shutdown () { if (sessionFactory != null && !sessionFactory.isClosed()) { sessionFactory.close(); } } }
三、实体映射详解 3.1 实体类设计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.example.entity;import lombok.Data;import lombok.NoArgsConstructor;import lombok.AllArgsConstructor;import lombok.Builder;import java.util.Date;@Data @NoArgsConstructor @AllArgsConstructor @Builder public class User { private Long id; private String username; private String password; private String email; private Integer status; private Date createdAt; private Date updatedAt; }
3.2 XML 映射文件(User.hbm.xml) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping > <class name ="com.example.entity.User" table ="users" > <id name ="id" column ="id" > <generator class ="native" /> </id > <property name ="username" column ="username" not-null ="true" unique ="true" /> <property name ="password" column ="password" not-null ="true" /> <property name ="email" column ="email" /> <property name ="status" column ="status" > <column name ="status" default ="1" /> </property > <property name ="createdAt" column ="created_at" /> <property name ="updatedAt" column ="updated_at" /> </class > </hibernate-mapping >
3.3 JPA 注解映射(推荐方式) 相比 XML 配置,注解方式更加简洁,是目前主流的选择:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.example.entity;import jakarta.persistence.*;import lombok.Data;import lombok.NoArgsConstructor;import lombok.AllArgsConstructor;import lombok.Builder;import java.util.Date;@Entity @Table(name = "users") @Data @NoArgsConstructor @AllArgsConstructor @Builder public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "username", nullable = false, unique = true) private String username; @Column(name = "password", nullable = false) private String password; @Column(name = "email") private String email; @Column(name = "status") private Integer status; @Column(name = "created_at") @Temporal(TemporalType.TIMESTAMP) private Date createdAt; @Column(name = "updated_at") @Temporal(TemporalType.TIMESTAMP) private Date updatedAt; }
3.4 主键生成策略
flowchart TD
A["主键生成策略"] --> B["IDENTITY\n自增"]
A --> C["SEQUENCE\n序列"]
A --> D["TABLE\n表生成"]
A --> E["UUID\n全局唯一"]
A --> F["AUTO\n自动选择"]
B --> B1["MySQL AUTO_INCREMENT"]
C --> C1["Oracle SEQUENCE"]
D --> D1["Hibernate 序列表"]
E --> E1["分布式环境"]
F --> F1["根据方言自动选择"]
style A fill:#fff3e0
style B fill:#c8e6c9
style C fill:#e3f2fd
style D fill:#fff3e0
style E fill:#f8bbd0
style F fill:#e3f2fd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq") @SequenceGenerator(name = "user_seq", sequenceName = "user_sequence", allocationSize = 1) private Long id;@Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "id_gen") @TableGenerator(name = "id_gen", table = "hibernate_sequences", pkColumnName = "sequence_name", valueColumnName = "next_val") private Long id;@Id @GeneratedValue(strategy = GenerationType.UUID) private String id; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;
3.5 属性映射细节 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Entity @Table(name = "users") public class User { private String username; @Column(name = "user_name", nullable = false, length = 50, unique = true) private String userName; @Transient private String temporaryField; @Enumerated(EnumType.STRING) private UserStatus status; @Lob private String description; @Lob private byte [] avatar; @Temporal(TemporalType.DATE) @Temporal(TemporalType.TIME) @Temporal(TemporalType.TIMESTAMP) private Date birthDate; } enum UserStatus { ACTIVE, INACTIVE, DELETED }
四、Hibernate 核心 API 4.1 核心对象关系
flowchart TD
A["🔧 Hibernate 核心 API"] --> B["📋 Configuration"]
A --> C["🏭 SessionFactory"]
A --> D["📦 Session"]
A --> E["🔒 Transaction"]
B -->|"buildSessionFactory()"| C
C -->|"openSession() / getCurrentSession()"| D
D -->|"beginTransaction()"| E
style A fill:#fff3e0
style C fill:#c8e6c9
style D fill:#c8e6c9
style E fill:#f8bbd0
API
说明
生命周期
Configuration
加载配置,构建 SessionFactory
应用级别
SessionFactory
创建 Session,重量级,线程安全
应用级别
Session
数据库会话,操作 CRUD
请求级别
Transaction
事务管理
业务方法级别
Query
执行 HQL 查询
查询执行完即可关闭
Criteria
面向对象查询
查询执行完即可关闭
4.2 Session 核心方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 session.save(entity); session.persist(entity); session.update(entity); session.saveOrUpdate(entity); session.delete(entity); session.get(Class, id); session.load(Class, id); session.createQuery(hql); session.createCriteria(Class); session.createSQLQuery(sql); Transaction tx = session.beginTransaction(); tx.commit(); tx.rollback(); session.flush(); session.clear(); session.evict(obj); session.contains(obj); session.close();
4.3 get vs load 区别 1 2 3 4 5 6 7 8 9 10 11 User user1 = session.get(User.class, 1L );System.out.println(user1); User user2 = session.load(User.class, 1L );System.out.println(user2);
特性
get()
load()
加载方式
立即加载
延迟加载(返回代理对象)
查不到时
返回 null
抛出异常
性能
每次都执行 SQL
性能更好(按需加载)
适用场景
确定对象存在
不确定对象是否存在时
五、CRUD 增删改查操作 5.1 插入数据(INSERT) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public class HibernateCRUD { private static SessionFactory factory = HibernateUtil.getSessionFactory(); public Long saveUser (User user) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); Long id = (Long) session.save(user); tx.commit(); System.out.println("✅ 用户保存成功,ID:" + id); return id; } } public void persistUser (User user) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); session.persist(user); tx.commit(); System.out.println("✅ 用户持久化成功" ); } } public void batchInsert (List<User> users) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); for (int i = 0 ; i < users.size(); i++) { session.persist(users.get(i)); if (i % 20 == 0 ) { session.flush(); session.clear(); } } tx.commit(); System.out.println("✅ 批量插入完成,共 " + users.size() + " 条" ); } } }
5.2 查询数据(SELECT) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public User findById (Long id) { try (Session session = factory.openSession()) { return session.get(User.class, id); } } public User findByIdLazy (Long id) { try (Session session = factory.openSession()) { User user = session.load(User.class, id); System.out.println("代理对象已创建:" + user.getClass().getName()); return user; } } public List<User> findAll () { try (Session session = factory.openSession()) { Query<User> query = session.createQuery( "FROM User ORDER BY createdAt DESC" , User.class); return query.list(); } } public List<User> findByStatus (Integer status) { try (Session session = factory.openSession()) { Query<User> query = session.createQuery( "FROM User WHERE status = :status ORDER BY createdAt DESC" , User.class); query.setParameter("status" , status); return query.list(); } } public List<User> findByPage (int page, int size) { try (Session session = factory.openSession()) { Query<User> query = session.createQuery( "FROM User ORDER BY createdAt DESC" , User.class); query.setFirstResult((page - 1 ) * size); query.setMaxResults(size); return query.list(); } }
5.3 更新数据(UPDATE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 public void updateUser (User user) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); session.update(user); tx.commit(); System.out.println("✅ 用户更新成功" ); } } public void mergeUser (User user) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); User merged = session.merge(user); tx.commit(); System.out.println("✅ 用户合并成功" ); } } public void dynamicUpdate (Long id, String newEmail) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); User user = session.get(User.class, id); if (user != null ) { if (newEmail != null && !newEmail.isEmpty()) { user.setEmail(newEmail); } session.update(user); } tx.commit(); } } public int batchUpdateStatus (List<Long> ids, Integer newStatus) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); Query<Integer> query = session.createQuery( "UPDATE User SET status = :status WHERE id IN :ids" , Integer.class); query.setParameter("status" , newStatus); query.setParameterList("ids" , ids); int rows = query.executeUpdate(); tx.commit(); System.out.println("✅ 批量更新了 " + rows + " 行" ); return rows; } }
5.4 删除数据(DELETE) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public void deleteUser (Long id) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); User user = session.get(User.class, id); if (user != null ) { session.delete(user); System.out.println("✅ 用户删除成功" ); } tx.commit(); } } public void deleteUserDirect (Long id) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); User user = new User (); user.setId(id); session.delete(user); tx.commit(); System.out.println("✅ 用户删除成功(直接删除)" ); } } public int batchDelete (List<Long> ids) { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); Query<Integer> query = session.createQuery( "DELETE FROM User WHERE id IN :ids" , Integer.class); query.setParameterList("ids" , ids); int rows = query.executeUpdate(); tx.commit(); System.out.println("✅ 批量删除了 " + rows + " 行" ); return rows; } }
六、对象状态与一级缓存 6.1 Hibernate 对象三种状态 理解 Hibernate 对象状态是掌握 Hibernate 的关键:
flowchart TD
A["🧩 Hibernate 对象状态"] --> B["瞬时状态\nTransient"]
A --> C["持久状态\nPersistent"]
A --> D["游离状态\nDetached"]
B --> B1["new 创建\n无 ID,无 Session 关联"]
B --> B2["save() / persist()\n➡️ 持久状态"]
C --> C1["有 ID\n有 Session 关联\n在一级缓存中"]
C --> C2["get() / load() / query\n➡️ 持久状态"]
C --> C3["commit()\n➡️ 游离状态"]
C --> C4["evict() / close()\n➡️ 游离状态"]
D --> D1["有 ID\n无 Session 关联\n不在缓存中"]
D --> D2["update() / saveOrUpdate()\n➡️ 持久状态"]
style A fill:#fff3e0
style B fill:#ffcdd2
style C fill:#c8e6c9
style D fill:#fff3e0
6.2 状态转换详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 User user = new User ();user.setUsername("test" ); user.setPassword("pass" ); session.save(user); user.setEmail("new@example.com" ); session.close(); User detachedUser = new User ();detachedUser.setId(1L ); detachedUser.setUsername("updated" ); session.update(detachedUser);
6.3 一级缓存机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public void cacheDemo () { try (Session session = factory.openSession()) { System.out.println("===== 一级缓存演示 =====" ); User u1 = session.get(User.class, 1L ); System.out.println("第一次查询:" + u1.getUsername()); User u2 = session.get(User.class, 1L ); System.out.println("第二次查询:" + u2.getUsername()); System.out.println("是否是同一对象:" + (u1 == u2)); session.evict(u1); User u3 = session.get(User.class, 1L ); System.out.println("evict 后查询:" + (u1 == u3)); session.clear(); } } public void dirtyCheckingDemo () { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); User user = session.get(User.class, 1L ); user.setEmail("dirty@example.com" ); user.setStatus(0 ); tx.commit(); System.out.println("✅ 脏检查自动更新了用户" ); } }
6.4 flush 机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public void flushDemo () { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); session.setFlushMode(FlushMode.AUTO); User user = session.get(User.class, 1L ); user.setStatus(0 ); session.flush(); tx.commit(); } }
七、映射关系配置 7.1 一对一关联(@OneToOne) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @Entity @Table(name = "user_profiles") @Data public class UserProfile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "real_name") private String realName; @Column(name = "id_card") private String idCard; @Column(name = "address") private String address; @OneToOne(mappedBy = "profile") private User user; } @Entity @Table(name = "users") @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String email; @OneToOne @JoinColumn(name = "profile_id") private UserProfile profile; }
1 2 3 <one-to-one name ="profile" class ="UserProfile" cascade ="all" />
7.2 一对多关联(@OneToMany) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 @Entity @Table(name = "users") @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Article> articles = new ArrayList <>(); } @Entity @Table(name = "articles") @Data public class Article { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; }
flowchart LR
A["👤 User"] -->|"一对多\n(1:N)"| B["📝 Article"]
B -->|"多对一\n(N:1)"| A
A -->|"articles"| A1["List"]
B -->|"user"| B1["User 对象"]
style A fill:#c8e6c9
style B fill:#e3f2fd
7.3 多对多关联(@ManyToMany) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @Entity @Table(name = "teachers") @Data public class Teacher { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany @JoinTable( name = "teacher_student", joinColumns = @JoinColumn(name = "teacher_id"), inverseJoinColumns = @JoinColumn(name = "student_id") ) private Set<Student> students = new HashSet <>(); } @Entity @Table(name = "students") @Data public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany(mappedBy = "students") private Set<Teacher> teachers = new HashSet <>(); }
7.4 级联操作(cascade) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 @Entity @Table(name = "users") @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<Article> articles = new ArrayList <>(); } public void cascadeSaveDemo () { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); User user = new User (); user.setUsername("author" ); user.setEmail("author@example.com" ); Article article = new Article (); article.setTitle("Hibernate 级联操作" ); article.setContent("本文讲解级联操作..." ); article.setUser(user); session.save(user); tx.commit(); System.out.println("✅ 级联保存成功" ); } } public void cascadeDeleteDemo () { try (Session session = factory.openSession()) { Transaction tx = session.beginTransaction(); User user = session.get(User.class, 1L ); session.delete(user); tx.commit(); System.out.println("✅ 级联删除成功(用户和文章都删了)" ); } }
八、HQL 查询语言 8.1 HQL 基础语法 HQL(Hibernate Query Language)是面向对象的查询语言,操作的是对象和属性:
flowchart TD
A["📝 SQL vs HQL"] --> B["SQL:面向表和列"]
A --> C["HQL:面向对象和属性"]
B --> B1["SELECT * FROM users"]
B1 --> B2["SELECT u.* FROM users u"]
B2 --> B3["SELECT * FROM users WHERE id = 1"]
C --> C1["FROM User"]
C1 --> C2["SELECT u FROM User u"]
C2 --> C3["FROM User WHERE id = 1"]
style A fill:#fff3e0
style B fill:#ffcdd2
style C fill:#c8e6c9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public void hqlDemo () { try (Session session = factory.openSession()) { Query<User> q1 = session.createQuery("FROM User" , User.class); List<User> users = q1.list(); Query<User> q2 = session.createQuery( "FROM User WHERE status = :status ORDER BY createdAt DESC" , User.class); q2.setParameter("status" , 1 ); List<User> activeUsers = q2.list(); Query<User> q3 = session.createQuery( "FROM User WHERE status = ?1 ORDER BY createdAt DESC" , User.class); q3.setParameter(1 , 1 ); Query<User> q4 = session.createQuery( "FROM User ORDER BY createdAt DESC" , User.class); q4.setFirstResult(0 ); q4.setMaxResults(10 ); List<User> page1 = q4.list(); Query<User> q5 = session.createQuery( "FROM User WHERE id = :id" , User.class); q5.setParameter("id" , 1L ); User user = q5.uniqueResult(); Query<Long> q6 = session.createQuery( "SELECT COUNT(*) FROM User" , Long.class); Long count = q6.uniqueResult(); Query<Object[]> q7 = session.createQuery( "SELECT u.id, u.username, u.email FROM User u" , Object[].class); List<Object[]> results = q7.list(); for (Object[] row : results) { System.out.println(row[0 ] + "-" + row[1 ] + "-" + row[2 ]); } } }
8.2 HQL 高级特性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 public void hqlAdvancedDemo () { try (Session session = factory.openSession()) { Query<User> q1 = session.createQuery( "FROM User WHERE username LIKE :kw" , User.class); q1.setParameter("kw" , "%test%" ); Query<User> q2 = session.createQuery( "FROM User WHERE status IN (:statuses)" , User.class); q2.setParameterList("statuses" , Arrays.asList(1 , 2 , 3 )); Query<User> q3 = session.createQuery( "FROM User WHERE id BETWEEN :min AND :max" , User.class); q3.setParameter("min" , 1L ); q3.setParameter("max" , 10L ); Query<User> q4 = session.createQuery( "FROM User WHERE email IS NULL OR email = ''" , User.class); Query<User> q5 = session.createQuery( "FROM User ORDER BY createdAt DESC, username ASC" , User.class); Query<Object[]> q6 = session.createQuery( "SELECT u.status, COUNT(u), MAX(u.createdAt) " + "FROM User u GROUP BY u.status" , Object[].class); List<Object[]> stats = q6.list(); for (Object[] row : stats) { System.out.println("状态 " + row[0 ] + ":共 " + row[1 ] + " 人,最新 " + row[2 ]); } Query<Object[]> q7 = session.createQuery( "SELECT u.status, COUNT(u) " + "FROM User u GROUP BY u.status HAVING COUNT(u) > 5" , Object[].class); Query<User> q8 = session.createQuery( "SELECT DISTINCT u FROM User u " + "LEFT JOIN FETCH u.articles " + "WHERE u.id = :id" , User.class); q8.setParameter("id" , 1L ); User user = q8.uniqueResult(); Query<User> q9 = session.createQuery( "FROM User WHERE status = (SELECT MAX(u.status) FROM User u)" , User.class); } }
8.3 原生 SQL 查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public void nativeSqlDemo () { try (Session session = factory.openSession()) { SQLQuery<User> q1 = session.createSQLQuery( "SELECT * FROM users WHERE status = :status" , User.class); q1.setParameter("status" , 1 ); List<User> users = q1.list(); SQLQuery<Object[]> q2 = session.createSQLQuery( "SELECT id, username, email FROM users" , Object[].class); List<Object[]> partialUsers = q2.list(); SQLQuery q3 = session.createSQLQuery("CALL get_user_stats()" ); SQLQuery q4 = session.createSQLQuery( "SELECT u.id, u.username, COUNT(a.id) as article_count " + "FROM users u LEFT JOIN articles a ON u.id = a.user_id " + "GROUP BY u.id, u.username" ); q4.addScalar("id" , LongType.INSTANCE); q4.addScalar("username" , StringType.INSTANCE); q4.addScalar("article_count" , LongType.INSTANCE); } }
九、事务管理 9.1 Hibernate 事务概念
flowchart TD
A["🔒 事务特性 ACID"] --> A1["A - Atomicity\n原子性"]
A --> A2["C - Consistency\n一致性"]
A --> A3["I - Isolation\n隔离性"]
A --> A4["D - Durability\n持久性"]
A1 --> A1a["全部成功\n或全部失败"]
A2 --> A2a["事务前后\n数据合法一致"]
A3 --> A3a["并发事务\n互不干扰"]
A4 --> A4a["提交后\n永久保存"]
style A fill:#fff3e0
style A1 fill:#c8e6c9
style A2 fill:#c8e6c9
style A3 fill:#fff3e0
style A4 fill:#f8bbd0
9.2 声明式事务(Spring 环境) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Override public void transfer (Long fromId, Long toId, BigDecimal amount) { User from = userRepository.findById(fromId); User to = userRepository.findById(toId); from.setBalance(from.getBalance().subtract(amount)); to.setBalance(to.getBalance().add(amount)); userRepository.save(from); userRepository.save(to); } }
9.3 编程式事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public void transactionDemo () { try (Session session = factory.openSession()) { Transaction tx = null ; try { tx = session.beginTransaction(); User user = new User (); user.setUsername("new_user" ); user.setPassword("pass" ); session.save(user); Article article = new Article (); article.setTitle("New Article" ); article.setUser(user); session.save(article); if (user.getBalance().compareTo(amount) < 0 ) { throw new RuntimeException ("余额不足" ); } tx.commit(); System.out.println("✅ 事务提交成功" ); } catch (Exception e) { if (tx != null ) { tx.rollback(); System.out.println("🔄 事务已回滚" ); } throw e; } } }
9.4 事务隔离级别 1 2 3 4 5 6 7 8 9 <property name ="hibernate.connection.isolation" > 2</property >
十、延迟加载与抓取策略 10.1 延迟加载(Lazy Loading) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void lazyLoadingDemo () { try (Session session = factory.openSession()) { User user = session.get(User.class, 1L ); System.out.println("用户:" + user.getUsername()); List<Article> articles = user.getArticles(); System.out.println("文章数:" + articles.size()); } } public void lazyLoadingSolutionDemo () { try (Session session = factory.openSession()) { User user = session.get(User.class, 1L ); Hibernate.initialize(user.getArticles()); } }
10.2 抓取策略(Fetch Strategy)
flowchart TD
A["⚡ 抓取策略"] --> B["立即加载\nEager"]
A --> C["延迟加载\nLazy"]
A --> D["批量抓取\nBatch"]
A --> E["子查询抓取\nSubselect"]
B --> B1["查询时立即\n加载关联对象"]
C --> C1["访问属性时\n才加载关联对象"]
D --> D1["批量加载\n多个代理对象"]
E --> E1["子查询\n一次加载"]
style A fill:#fff3e0
style B fill:#ffcdd2
style C fill:#c8e6c9
style D fill:#fff3e0
style E fill:#e3f2fd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Entity @Table(name = "users") @Data public class User { @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) private List<Article> articles; @BatchSize(size = 20) private List<Article> articles2; } public void joinFetchDemo () { try (Session session = factory.openSession()) { Query<User> query = session.createQuery( "SELECT DISTINCT u FROM User u " + "LEFT JOIN FETCH u.articles " + "WHERE u.id = :id" , User.class); query.setParameter("id" , 1L ); User user = query.uniqueResult(); } }
10.3 N+1 问题与解决 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public void nPlusOneDemo () { try (Session session = factory.openSession()) { List<User> users = session.createQuery("FROM User" , User.class).list(); for (User user : users) { System.out.println(user.getUsername() + " - " + user.getArticles().size()); } } } public void solveNPlusOneDemo () { try (Session session = factory.openSession()) { Query<User> query = session.createQuery( "SELECT DISTINCT u FROM User u " + "LEFT JOIN FETCH u.articles" , User.class); List<User> users = query.list(); for (User user : users) { System.out.println(user.getUsername() + " - " + user.getArticles().size()); } } }
十一、与 Spring 集成 11.1 Spring + Hibernate 整合配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Configuration @EnableTransactionManagement public class HibernateConfig { @Bean public LocalSessionFactoryBean sessionFactory (DataSource dataSource) { LocalSessionFactoryBean factory = new LocalSessionFactoryBean (); factory.setDataSource(dataSource); factory.setPackagesToScan("com.example.entity" ); factory.setHibernateProperties(hibernateProperties()); return factory; } @Bean public Properties hibernateProperties () { Properties props = new Properties (); props.setProperty("hibernate.dialect" , "org.hibernate.dialect.MySQLDialect" ); props.setProperty("hibernate.show_sql" , "true" ); props.setProperty("hibernate.format_sql" , "true" ); props.setProperty("hibernate.hbm2ddl.auto" , "update" ); props.setProperty("hibernate.cache.use_second_level_cache" , "true" ); return props; } @Bean public HibernateTransactionManager transactionManager (SessionFactory sessionFactory) { return new HibernateTransactionManager (sessionFactory); } }
11.2 Spring Data JPA 简化开发 Spring Data JPA 是 Spring 生态中简化 JPA/Hibernate 开发的利器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public interface UserRepository extends JpaRepository <User, Long> { List<User> findByUsername (String username) ; List<User> findByStatus (Integer status) ; List<User> findByUsernameContainingAndStatus (String keyword, Integer status) ; @Query("FROM User WHERE username = :username") User findUserByUsername (@Param("username") String username) ; @Modifying @Query("UPDATE User SET status = :status WHERE id = :id") int updateStatus (@Param("id") Long id, @Param("status") Integer status) ; } @Service @Transactional public class UserService { @Autowired private UserRepository userRepository; public User getById (Long id) { return userRepository.findById(id).orElse(null ); } public List<User> getActiveUsers () { return userRepository.findByStatus(1 ); } public User getByUsername (String username) { return userRepository.findUserByUsername(username); } }
十二、常见问题与最佳实践 12.1 常见问题与解决方案
flowchart TD
A["❓ 常见问题"] --> B["LazyInitializationException"]
A --> C["N+1 查询"]
A --> D["事务未提交"]
A --> E["对象状态混乱"]
B --> B1["✅ Session 已关闭\n访问懒加载对象"]
B1 --> B2["方案:\nJOIN FETCH\n或开启 long Session"]
C --> C1["✅ 查询 N+1\n性能问题"]
C1 --> C2["方案:\n+1 配置\n或 JOIN FETCH"]
D --> D1["✅ 数据未保存\n到数据库"]
D1 --> D2["方案:\n检查事务配置\n是否 @Transactional"]
E --> E1["✅ 对象状态\n不符合预期"]
E1 --> E2["方案:\n理解三种状态\n使用 merge()"]
style A fill:#fff3e0
12.2 性能优化技巧 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Query<User> query = session.createQuery( "SELECT DISTINCT u FROM User u " + "LEFT JOIN FETCH u.articles " + "WHERE u.id = :id" , User.class); @OneToMany(mappedBy = "user") @BatchSize(size = 20) private List<Article> articles;@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @Entity @Table(name = "users") public class User { } Query<Object[]> query = session.createQuery( "SELECT u.id, u.username FROM User u" , Object[].class); Query<User> query = session.createQuery( "FROM User ORDER BY createdAt DESC" , User.class); query.setFirstResult(0 ); query.setMaxResults(20 ); try (Session session = factory.openSession()) { }
12.3 配置清单 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <session-factory > <property name ="hibernate.show_sql" > true</property > <property name ="hibernate.format_sql" > true</property > <property name ="hibernate.hbm2ddl.auto" > update</property > <property name ="hibernate.jdbc.batch_size" > 20</property > <property name ="hibernate.order_inserts" > true</property > <property name ="hibernate.order_updates" > true</property > <property name ="hibernate.jdbc.batch_versioned_data" > true</property > <property name ="hibernate.cache.use_second_level_cache" > true</property > <property name ="hibernate.cache.use_query_cache" > true</property > </session-factory >
十三、总结 13.1 核心知识点回顾
mindmap
root((Hibernate 核心知识))
基础入门
ORM 概念
环境搭建
配置详解
实体映射
XML 映射
JPA 注解
主键生成策略
核心 API
SessionFactory
Session
Transaction
get vs load
对象状态
瞬时状态
持久状态
游离状态
一级缓存
脏检查
映射关系
一对一
一对多
多对多
级联操作
HQL 查询
查询语法
参数绑定
聚合函数
原生 SQL
性能优化
延迟加载
JOIN FETCH
批量抓取
二级缓存
Spring 集成
Spring Data JPA
事务管理
配置优化
13.2 学习路线建议
flowchart LR
A["第一阶段\n入门"] --> B["第二阶段\n核心概念"]
B --> C["第三阶段\n映射配置"]
C --> D["第四阶段\nHQL 查询"]
D --> E["第五阶段\n高级特性"]
E --> F["第六阶段\nSpring 集成"]
A --> A1["ORM 概念"]
A --> A2["环境搭建"]
B --> B1["对象状态"]
B --> B2["Session API"]
B --> B3["事务管理"]
C --> C1["实体映射"]
C --> C2["关联映射"]
C --> C3["级联操作"]
D --> D1["HQL 语法"]
D --> D2["参数绑定"]
D --> D3["原生 SQL"]
E --> E1["缓存机制"]
E --> E2["性能优化"]
E --> E3["延迟加载"]
F --> F1["Spring Data JPA"]
F --> F2["声明式事务"]
F --> F3["配置调优"]
style A fill:#e3f2fd
style B fill:#c8e6c9
style C fill:#fff3e0
style D fill:#f8bbd0
style E fill:#ffcdd2
style F fill:#e3f2fd
13.3 下一步推荐学习
📖 Spring Data JPA :简化 JPA/Hibernate 开发
📖 MyBatis :对比学习半自动 ORM
📖 Hibernate 源码 :理解框架设计思想
📖 数据库优化 :索引、SQL 调优
📖 分布式数据库 :分库分表、读写分离
💡 写给读者的话 :Hibernate 虽然在国内被 MyBatis 盖过了风头,但它在 ORM 领域的经典地位和设计思想依然值得深入学习。理解 Hibernate 的对象状态、缓存机制、延迟加载等核心概念,对你理解其他 ORM 框架甚至整个 Java 持久层生态都有极大帮助。无论是 Hibernate 还是 MyBatis,选择合适的工具做好工作才是最重要的!🚀
📅 本文首次发布于 2026 年 5 月 24 日