Session接口是Hibernate应用使用最广泛的接口,Session也被称为持久化管理器。Session对象是Hibernate技术的核心,持久化化对象的生命周期、事务的管理和持久化对象的查询、更新和删除都是通过Session对象来完成的。
Session接口是一个非线程安全的,避免多个线程共享一个Session实例。Session对象通过SessionFactory对象的getCurrentSession()或者openSession()方法获取,示例代码如下:
Session session = sessionFactory.openSession();
Session session = sessionFactory.getCurrentSession();
Session对象获取后,不会立刻获取Connection对象,而是在Session对象需要对数据库进行操作时才会从数据库连接池中获取Connection对象。而关闭Session对象时,不会直接关闭Connection,而是将Connection对象返回到连接池中。
在Hibernate 3.1版本之后,可以通过在hibernate.cfg.xml文件中配置以下内容:
<property name="current_session_context_class">thread</property>
配置后表明Hibernate使用ThreadLocal对象来管理Session对象,ThreadLocal对象应用了Thread-Specific Storage设计模式。这种模式可以有效隔离线程所使用的数据,所以避开了Session对象在多线程情况下的数据共享问题。使用这个配置信息之后,Session对象只能通过SessionFactory对象的getCurrentSession()方法获取。
早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。
ThreadLocal和线程同步机制一样都是为了解决多线程中相同变量的访问冲突问题。
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
ThreadLocal类接口如下:
- void set(Object value)设置当前线程的线程局部变量的值。
- public Object get()该方法返回当前线程所对应的线程局部变量。
- public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
- protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计。此方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中缺省实现直接返回一个null。
Session接口用于进行CRUD操作的方法
Java对象在hibernate持久化层的状态:
临时态:不被session关联,在数据库中没有相应的记录
持久态:被session关联,在数据库中有对应的记录
删除态:不被session关联,并且session已经计划从数据库中删除
游离态:不被session关联,在数据库中有对应的记录
(一)get(Class clazz, Serializable id)
首先根据id在session缓存(一级缓存)查询,没有的话查询二级缓存,最后查询数据库,查不到就返回null。
(二)load(Class theClass, Serializable id)
此方法默认认定id对应的对象(数据库记录)在数据库中是一定存在的,如果数据库中不存在该记录,则抛出异常。
首先根据id在session缓存(一级缓存)查询,没有的话查询数据库,查不到就抛出异常。
(三)save(Object object)
用来保存持久化对象,即在数据库中新增记录。
(四)saveOrUpdate(object);
根据对象的状态(临时,持久,托管)对对象进行save或update操作。
当对象的状态为临时状态时,对对象进行save操作
当对象的状态为持久或托管状态时,对对象进行update操作
(五)update(Object object)
使一个游离对象转变为持久化对象。
Session只有在清理缓存的时候才执行update语句,并且在执行的时候才会把对象的当前属性封装到update语句中,因此程序多次修改对象的属性,在清理缓存的时候只会执行一次update语句。
用update()关联一个对象的时候,若缓存中已经存在了同类型并且OID相同的对象,就会报错,应该改用merge()。
(六)delete(Object object)
删除游离态对象或是持久态对象,若删除的是游离态对象,先将对象变为持久态。
使用delete()方法删除数据库表中的一条记录,首先要通过该对象的get()或者load()方法获取要删除记录对应的持久化对象,然后通过delete()方法删除。
(七)merge(Object object)
将一个游离对象的属性复制到一个持久化对象中。其处理流程如下:
(1)根据游离对象的id到Session缓存中查找匹配的持久化对象。若找到匹配的持久化对象,则将游离对象的属性复制到持久化对象中,计划实行一条update语句,然后返回持久化对象的引用。
(2)如果在Session的缓存中没有找到与游离对象id一致的持久化对象,那么就试图根据该id从数据库中加载持久化对象。如果数据库中存在匹配的持久化对象,则将游离对象的属性复制到刚加载的持久化对象中,计划实行一条update语句,然后返回持久化对象的引用。
(3)如果数据库中也不存在或者对象是临时对象时,则会新建一个对象,将属性赋值到该新建对象中,再持久化新建对象,最后返回新建对象的引用。
merge()执行后,该对象状态为游离态