Hibernate部分AP详解

1.Configuration 接口

org.hibernate.cfg.Configuration 接口的作用是加载主配置文件及映射文件,以实现对Hibernate 的启动。

Configuration 实例的获取方式:Configuration cfg = new Configuration().configure();

(1)new Configuration()

new Configuration()会加载一个属性文件 hibernate.properties。该属性文件中存放着数据连接配置、Hibernate 配置等配置信息。一般情况下不用设置该属性文件,其设置已经放到了主配置文件中。若要设置,应将其放于 src 目录下。该文件的模板存放于 Hibernate 框架解压目录下的 project/etc 下。
(2)无参 configure()方法

configure()方法,默认用于加载和解析名称为 hibernate.cfg.xml 的配置文件,并通过主配置文件找到并解析映射文件。该方法返回一个 Configuration 对象。所以,cfg 是一个包含配置信息及映射信息的 Configuration 对象.

(3)带参 configure()方法

Hibernate 主配置文件默认名称为 hibernate.cfg.xml,应存放在 src 类路径下。但也可以更换路径与文件名。此时,需要使用带参的 configuraion()方法。

2.SessionFactory接口

org.hibernate. SessionFactory 接口对象是由 Configuration 对象通过 buildSessionFactory()方法创建。创建该对象的目的是,用于开启 Session 对象。SessionFactory sessionFactory = cfg.buildSessionFactory();

(1)SessionFactory 对象特点

重量级对象(系统开销大)、单例的、线程安全的。
按理说,单例对象一定是被共享的,是线程不安全的。但查看 SessionFactory 接口的实现类 SessionFactoryImpl 源码,可以看其大多数成员变量是 final 的,所以其是线程安全的。

(2)SessionFactory 对象的使用原则
基于其是线程安全的重量级对象,其创建与销毁时系统开销大,又是单例的特点,SessionFactory 对象一般不手工关闭,而是在应用结束时自动将其销毁。因此,SessionFactory不用进行 close()关闭。

3.Session接口

org.hibernate.classic.Session 接口是应用程序与 Hibernate 连接的核心 API,是 Hibernate向应用程序提供的操纵 DB 的最主要接口。它提供了基本的保存、更新、删除与查询方法。由 SessionFactory 对象创建。

Session s= sessionFactory.getCurrentSession();

(1)Session 对象的特点

一个轻量级对象、线程不安全的、多例的。

在 Web 应用中,多个用户对同一应用访问,Hibernate 会为每个用户创建一个 Session对象。所以是多例的。Session 中包含大量非 final 成员变量,对于同一个用户的操作,可能会产生多个事务,这多个事务若同时对同一个 Session 的同一个成员变量进行访问,就会引起并发问题。所以 session 是线程不安全的。

(2)Session 对象的使用

基于 Session 的以上特点,Session 在使用时要做到一个线程一个 Session,即一个事务一个 Session。使用完毕,立即关闭。Session 不要作为某个类的成员变量出现,因为这样会出现多个实例对象对同一个 session 的共享,使其更不安全。

(3)Session 对象的获取

SessionFactory 对于 Session 对象的获取,提供了两种获取方式:

  • sessionFactory.openSession():创建一个新的 Session 对象
  • sessionFactory.getCurrentSession():获取当前线程中的 Session 对象

为了保证一个线程一个 Session,即一个线程中使用的 Session 是同一个对象,一般在获取 Session 对象时,使用 SessionFactory 的 getCurrentSession()方法。不过,使用该方法获取Session 对象,需要在主配置文件中对 Session 所处的上下文环境,即事务环境进行注册。

<property name="hibernate.current_session_context_class">thread</property>

hibernate.current_session_context_class 取值有三种:

hibernate.current_session_context_class 的三种取值
取值意义
thread表示当前Session所处的环境为本地事务环境,Session会与当前线程绑定
jta表示当前Session所处的环境为分布式事务环境
SpringSessionContext类SSH整合时使用。表示将当前Session的管理权交由Spring容器,而Spring容器中会有事务环境。即当前Session所处的环境为Spring事务环境。

 

 为什么 getCurrentSession()方式获取到的是同一个对象?

getCurrentSession()首先会获取到当前线程 Thread.currentThread(),然后从 ThreadLocal中读取 key 为当前线程的 value。而该 value 即为当前线程中的 Session 对象。

ThreadLocal 是用于在线程中共享数据的。其底层为 Map<Thread, Object>,即该 map 的key 为线程 Thread,而 value 则为要共享的数据。

当在 Hibernate 主配置文件中设置了 hibernate.current_session_context_class 属性的值为thread 时,就表明每个用户获取到的 Session 对象都是自己当前线程中的Session,是同一个Session。

(4)Session关闭

使用 getCurrentSession()方法获取的 Session,在进行事务提交或回滚后,会自动关闭,无需再手工进行 close()。当然,也不能在最后的 finally{}语句块中对 Session 进行手工关闭。因为,无论是执行事务的 commit(),还是执行 rollback(),均会在 finally{}之前执行。也就是说,在执行 finally{}之前,session 已经关闭。若再手工关闭,将抛出异常。

总结:两种获取 Session 对象方式的区别

 getCurrentSession()方式openSession()方式
获取的对象无论执行多少次该方法,只要是在同一线程中,获取的都是同一个Session对象每执行一次该方法,获取到的都是一个新的Session对象。
对象的关闭自动关闭Session,无需手工关闭必须手工关闭Session对象
环境的注册需要注册Session的运行环境无需注册
查询对事物的支持查询必须在事务内执行查询可以不再事务内执行

 4.Transaction接口

通过该接口,可以将事务从持久层,提升到业务层。由 Session 对象创建。
session.getTransaction();
事务的开启:session.beginTransaction(); 或 session.getTransaction().begin();
事务的提交:session.getTransaction().commit();
事务的回滚:session.getTransaction().rollback();

5.总结 -- 单例、多例与线程安全问题

单例与多例问题是指,当多个用户访问某个类时,系统是为每个用户创建一个该类实例,还是整个系统无论多少用户访问,只创建一个该类实例。线程安全问题是指,多个用户同时在访问同一个程序时,其对于某一数据的修改,会不会影响到其他用户中的该数据。若没有影响,则是线程安全的;若有可能影响,则是线程不安全的。

(1)HttpServlet

其是单例的。即无论多少用户访问同一个业务,如 LoginServlet,Web 容器只会创建一个该 Servlet 实例。而该实例是允许多用户访问的。若 Servlet 中包含成员变量,则每个用户对于成员变量的修改,均会影响到其他用户所看到的该变量的值,所以这时是线程不安全的。若不包含成员变量,则是线程安全的。

(2)HttpSession

其是多例的。Web 容器会为每个用户开辟一个 Session,多个用户会有多个 Session。而每个用户只能访问自己的 Session。所以,对于 Session 来说,就不存在并发访问的情况,也就不存在线程安全的问题了。所以可以说是线程安全的。

(3)Struts2的Action

其是多例的。对于同一个业务,例如 LoginAction,系统会为每一个用户创建一个LoginAction 的实例,并使其成员变量 username 与 password 接收用户提交的数据。同一用户只能访问自己的 Action。所以,对于 Action 来说,就不存在并发访问的情况,也就不存在线程安全的问题了。所以可以说是线程安全的。

(4)Hibernate的SessionFactory

其是单例的。无论多少用户访问该项目,系统只会创建一个 SessionFactory 对象,即这个对象是可以被所有用户访问的。SessionFactory 实现类中所包含的成员变量基本都是 final 常量,即任何用户均不能修改。所以,也就不存在用户的修改对其他用户的影响问题了,所以是线程安全的。

(5)Hibernate的Session

其是多例的。系统会为每个用户创建一个 Session。Session 的实现类中定义了很多的非 final 成员变量,一个事务对成员变量所做的修改,会影响到另一个事务对同一数据的访问结果,所以是线程不安全的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值