上一篇
Hibernate中获取Session的两种方式代码示例
- 行业动态
- 2025-05-11
- 12
Hibernate获取Session的两种方式:①SessionFactory.openSession();②通过ContextualSession(如Spring整合时this.getSession(
通过SessionFactory.openSession()手动获取
核心特点
- 非事务绑定:需手动管理事务和Session生命周期。
- 灵活性高:适用于独立操作或非事务性场景。
- 显式关闭:必须手动调用
session.close()
释放资源。
代码示例
// 1. 创建SessionFactory(通常作为单例) Configuration config = new Configuration().configure(); // 读取hibernate.cfg.xml SessionFactory sessionFactory = config.buildSessionFactory(); // 2. 获取Session Session session = null; Transaction transaction = null; try { session = sessionFactory.openSession(); // 手动打开Session transaction = session.beginTransaction(); // 开启事务 // 执行数据库操作(例如保存实体) session.save(entity); transaction.commit(); // 提交事务 } catch (Exception e) { if (transaction != null) { transaction.rollback(); // 回滚事务 } e.printStackTrace(); } finally { if (session != null) { session.close(); // 必须手动关闭Session } }
关键步骤解析
步骤 | 作用 | 注意事项 |
---|---|---|
openSession() | 创建新Session | 每次调用返回独立Session,需显式关闭 |
beginTransaction() | 开启事务 | 需在操作前开启,否则无法提交/回滚 |
commit() | 提交事务 | 需在操作成功后调用 |
rollback() | 回滚事务 | 在异常捕获时调用 |
close() | 释放资源 | 必须放在finally 块中防止泄漏 |
通过SessionFactory.getCurrentSession()绑定线程
核心特点
- 事务绑定:需配置
current_session_context_class
为thread
或jta
。 - 自动管理:Session生命周期与事务绑定,提交后自动关闭。
- 线程安全:每个线程独享Session,适合Web应用。
代码示例
<!-hibernate.cfg.xml 配置 --> <property name="hibernate.current_session_context_class">thread</property>
// 1. 创建SessionFactory(同上) SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); // 2. 获取当前线程的Session Session session = null; Transaction transaction = null; try { session = sessionFactory.getCurrentSession(); // 获取线程绑定的Session transaction = session.beginTransaction(); // 开启事务 // 执行数据库操作(例如更新实体) session.update(entity); transaction.commit(); // 提交事务(Session自动关闭) } catch (Exception e) { if (transaction != null) { transaction.rollback(); // 回滚事务 } e.printStackTrace(); }
关键步骤解析
配置项 | 作用 | 注意事项 |
---|---|---|
current_session_context_class | 指定Session上下文 | thread 表示绑定到当前线程,jta 用于容器事务 |
getCurrentSession() | 获取线程绑定的Session | 若未开启事务,可能抛出HibernateException |
自动关闭 | 事务提交后自动关闭 | 无需显式调用close() ,但需确保事务正常结束 |
两种方式对比表
特性 | 方式一(openSession) | 方式二(getCurrentSession) |
---|---|---|
事务绑定 | 无 | 需配置current_session_context_class |
Session生命周期 | 手动管理 | 自动与线程/事务绑定 |
资源释放 | 必须显式close() | 事务提交后自动关闭 |
适用场景 | 独立操作、非事务性任务 | Web应用、长事务操作 |
异常处理 | 需手动回滚 | 依赖容器或框架管理 |
线程安全 | 需手动控制 | 天然线程安全(每个线程独立Session) |
注意事项
资源泄漏风险
- 方式一中若忘记
session.close()
,可能导致数据库连接耗尽,建议使用try-with-resources
(Java 7+)或始终在finally
块中关闭。 - 方式二需确保事务正常提交或回滚,否则Session可能不会自动关闭。
- 方式一中若忘记
事务传播问题
- 方式二依赖外部事务管理(如Spring或JTA),若在无事务环境下调用
getCurrentSession()
,会抛出NonUniqueObjectException
。
- 方式二依赖外部事务管理(如Spring或JTA),若在无事务环境下调用
性能优化
- 方式一适合短生命周期操作,避免频繁创建Session。
- 方式二在Web应用中可结合线程池复用Session,减少创建开销。
FAQs
问题1:为什么推荐在Web应用中使用getCurrentSession()
?
答:Web应用通常基于线程模型处理请求,getCurrentSession()
能自动绑定Session到当前线程,避免手动传递Session对象,结合Spring等框架时,可利用事务管理器(如@Transactional
)自动管理事务和Session生命周期,简化代码并提高安全性。
问题2:openSession()
和getCurrentSession()
能否混合使用?
答:不建议混合使用,两者管理Session的机制不同,混合可能导致资源冲突或异常,若同一线程先调用openSession()
再调用getCurrentSession()
,可能创建多个Session实例,导致数据不一致或连接泄漏,建议根据项目需求统一选择一种