hibernate session

Hibernate Session

  1. session 实例的生命周期
  2. session 缓存(一级缓存)

Session 缓存:

这里写图片描述

  1. flush() 方法:同步缓存修改的内容至数据库,commit()事务提交时会先进行flush操作,调用此函数可能会发送一系列sql至数据库(缓存数据的状态与数据库数据的状态是否一致),但不提交事务
  2. refresh() 方法:从数据库重新查询最新的数据,覆盖缓存内容的修改,调用此函数一定会发送sql至数据库,但是需要注意如果数据库隔离级别为可重复读时,会导致同一事务内相同sql所读的数据是一致的
  3. clear() 方法:清空缓存
  4. evict() 方法:指定某对象缓存过期,即调用后无法进行隐式更新数据库
  5. 同一个session不允许持有多个相同OID的对象,否则抛出异常
  6. 有些操作会导致提前进行flush操作:
1. HQL和Criteria的查询,每次进行查询前,都先会将session缓存中已经被修改的游离状态对象flush到数据库,然后再进行查询,为了保证每次查询都能得到最新的结果

2. OID需要使用数据库生成主键时(native)调用save()方法,因为调用完save方法后必须保证OID非null,所以会导致先发送sql至数据库,如果使用其他主键生成方式,不会提前sql发送
同一个session不允许持有多个相同OID的对象,否则抛出异常:
==============================================
            // session - 1
            Session session = ourSessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            // session - 1 obj
            StudentEntity entity1 = session.get(StudentEntity.class, 1);
            transaction.commit();
            session.close();

            // session - 2
            session = ourSessionFactory.openSession();
            transaction = session.beginTransaction();
            // session - 2 OID==1的对象在缓存中已存在
            StudentEntity entity2 = session.get(StudentEntity.class, 1);

            entity1.setName("haha");
            // 这时候缓存中就出现了两个OID==1的对象,抛异常
            session.update(entity1);

            transaction.commit();
            session.close();
            ourSessionFactory.close();

这里写图片描述

Session对象的四种状态以及转换

这里写图片描述

  1. 临时状态:通过new产生的对象,调用save、saveOrUpdate、persist等方法变成持久化状态
  2. 持久化状态:已经被持久化(OID非空且与数据库主键一一对应),加入到Session的缓存中,可调用delete方法变为删除状态,调用clear、evict等方法变为游离状态
  3. 游离状态:已经被持久化,但不再处于Session的缓存中,调用update、saveOrUpdate等方法变为持久化状态,调用delete方法变为删除状态
  4. 删除状态:OID不为null,从一个Session实例的缓存中删除。被删除对象和数据库中的相关记录对应。Session已经计划将其从数据库中删除。Session在清理缓存时,会执行SQL delete语句,删除数据库中的相应记录

save和persist方法持久化对象区别

  1. save方法,无论id是否为null,save方法后会重新分配id,save方法调用后id不能修改
  2. persist方法,id必须为空,否则抛异常
            StudentEntity entity = new StudentEntity();
            entity.setName("test");
            session.save(entity);
            entity.setId(10000);
            // 抛异常:
            // javax.persistence.PersistenceException: org.hibernate.HibernateException: identifier of an instance of org.digdata.whf.entiy.StudentEntity was altered from 103 to 10000

get和load方法获取持久化对象区别

  1. 加载的时间:调用get方法会立即发送sql查询数据库,立即加载;load方法返回的是一个代理对象,只有当使用到该对象的属性时才会发送sql查询并且初始化对象,延迟加载
  2. 根据不存在的主键查询对象的处理:get方法会返回null,load方法直接抛出异常
  3. load方法可能会抛出LazyInitializationException异常,若session在使用代理对象先close掉,会抛出异常
  4. load()方法会使用二级缓存,而get()方法在一级缓存没有找到的情况下会直接查询数据库,不会去二级缓存中查找。在使用中,对使用了二级缓存的对象进行查询时最好使用load()方法,以充分利用二级缓存来提高检索的效率。

update方法、隐式更新、saveOrUpdate方法数据区别

  1. update方法适用于跨session更新,调用时一定会发送sql至数据库,当更新不存在的对象时,抛异常,可使用select-before-update=true,避免盲目发送sql请求,但是效率不高,不推荐使用
  2. 隐式更新依赖缓存,不适用跨session,当缓存中的数据与数据库的数据不一致时,才会发送sql至数据库
  3. saveOrUpdate:当id为null,执行save操作;当id不为null且与数据库主键对应,执行update操作;当id不为null且与数据库主键不对应,抛异常

delete方法后游离对象的id设置为null

use_identifier_rollback=true

hibernate+数据库触发器可能导致的问题

  1. hibernate的update方法默认会直接发送sql至数据库,若数据有update的触发器,会导致触发器也盲目的触发
  2. 若触发器修改了记录,session缓存无法感知到数据库数据的改变(flush+refresh)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值