题目
Hibernate中get()和load()方法的区别及使用场景
信息
- 类型:问答
- 难度:⭐⭐
考点
Session方法区别,延迟加载原理,异常处理,性能优化
快速回答
核心区别:
get()立即查询数据库,返回实体对象或nullload()返回代理对象,访问非ID属性时触发查询(延迟加载)
使用场景:
- 需立即访问数据 → 用
get() - 仅需关联对象引用 → 用
load()
1. 核心区别
get()方法:
- 立即访问数据库执行SELECT查询
- 对象不存在时返回
null - 返回真实实体对象
load()方法:
- 返回代理对象(Hibernate动态生成)
- 首次访问非ID属性时触发查询(延迟加载)
- 对象不存在时抛出
ObjectNotFoundException
2. 代码示例
// get() 示例
Employee emp1 = session.get(Employee.class, 101);
if (emp1 != null) {
System.out.println(emp1.getName()); // 立即访问属性
}
// load() 示例
Employee emp2 = session.load(Employee.class, 102);
System.out.println("代理对象已创建"); // 此时未查询数据库
System.out.println(emp2.getName()); // 此处触发SQL查询3. 原理说明
load()延迟加载机制:
- Hibernate通过
javassist或CGLIB生成代理对象 - 代理对象仅包含ID值,其他属性为
null - 首次调用非ID属性的getter方法时,执行数据库查询(
initialize())
执行过程对比:
| 方法 | SQL触发时机 | 返回值类型 | 不存在时行为 |
|---|---|---|---|
| get() | 调用时立即触发 | 实体类实例 | 返回null |
| load() | 首次访问属性时触发 | 代理对象 | 抛异常 |
4. 最佳实践
- 使用get()的场景:
- 需要立即使用对象属性(如显示用户详情)
- 不确定对象是否存在(需处理null值)
- 使用load()的场景:
- 仅需建立关联(如
order.setCustomer(customerProxy)) - 确定对象必然存在(如外键约束保证)
- 批量处理时减少即时查询压力
- 仅需建立关联(如
5. 常见错误
- LazyInitializationException:
- 在Session关闭后访问load()返回的代理对象属性
- 解决方案:使用
OpenSessionInView或提前初始化
- 无效的ID传递:
- load()使用不存在的ID导致后续操作崩溃
- 解决方案:重要操作前用
get()验证
- N+1查询问题:
- 循环中调用load()导致多次查询
- 解决方案:改用
get()或批量预加载
6. 扩展知识
- 性能优化:
- load()适合关联对象插入(避免额外SELECT)
- 结合
batch-size优化延迟加载
- JPA等价方法:
EntityManager.find()→ 类似get()EntityManager.getReference()→ 类似load()
- 代理对象检测:
- 使用
Hibernate.isInitialized(proxy)检查状态 - 通过
Hibernate.initialize(proxy)强制初始化
- 使用