在Hibernate,会有编码顺序和SQL语句顺序不一致情况,要从对象状态角度思考;
session的方法,导致对象状态的改变,从而才发送SQL
临时状态
- 无id,数据库中没有对应的值
- new 出一个对象后
- 删除状态的事务提交后
持久化状态
- 存于Hibernate的一级缓存中,数据库有对应的值,被Hibernate管理
- save,get,load,query.list,update 执行这些方法后,操作或返回的对象,都是持久化状态的对象.
游离状态
- 数据库有对应的值,一级缓存中没有对应的值
- session.close();关闭session后,一级缓存失去作用
- session.clear();清空 一级缓存的全部对象
- session.evict(A); 清空一级缓存中的A对象
删除状态
- session.delete(对象),该对象成为删除状态
- 此时数据库依然有值,待session刷新或事务提交,才删除变成临时状态.
- session.flush();刷新 session
快照区(数据库的投影)
- 当查询对象,会一式两份,一个存入缓存,一个存入快照
- 当修改持久化对象
- 修改一级缓存中的数据(变成脏的持久化对象),快照中不变,
- 提交时候,快照向一级缓存看齐而修改数据
- 当添加对象,
- 在一级缓存中添加对象,快照不变,
- 提交时候,快照向一级缓存看齐而修改数据
- 当删除持久化的对象,
- 在一级缓存中删除,快照不变
- 提交时候,快照向一级缓存看齐而修改数据
案例
- 情况1:native方式生成主键
session.save(对象);
syso("_________")
- 结果:
- 1.保存对象的sql
- 2.输出横线
- 原因:调用sava变成持久化状态需要其id才可以存入一级缓存;而id由数据库生成, 所以必须马上执行sql.返回id,将对象变成持久化对象.
- 情况2:increment方式生成主键
session.save(对象);
syso("_________")
- 结果:
- 1.输出横线
- 2.保存对象的sql
- 原因:此时的id由Hibernate生成,可以将对象直接存入一级缓存,当提交事务时候,才去对比一级缓存(有该对象)和快照区(无该对象),将sql补上
- 情况3:increment方式生成主键
session.save(对象);
session.clear();
- 结果:没有保存的sql
- 原因:保存了对象后,没有访问数据库,因为有id直接存入一级缓存
- 之后有清空了一级缓存,对比快照区,就不用添加了.
- 情况4:删除
session.delete(对象);
syso("___________")
- 结果:先横线,在发删除sql
- 原因:删除对象后,变成删除状态,执行提交时候,才会对比快照,进行sql
- 情况4:删除
session.delete(e);//e.id=2L
Employee e2=(Employee)session.get(Employee.class, 2L);
System.out.println(e2);
- 结果:1.null;2.发送删除语句
- 原因:e已经变成删除状态,查询删除状态对象,不发sql,直接null;
-
- 情况5:修改持久化对象
Employee e=(Employee)session.get(Employee.class, 3L);
e.setName("news");
- 结果:1.查找sql;2.修改sql
- 原因:查询时候,一式两份:一级缓存+快照区,返回一级缓存区的对象.修改后,一级缓存的对象变成脏的持久化状态.提交事务或更新session,快照向一级缓存看齐而修改数据
总结
我们操作与得到的都说一级缓存的数据,session.flush()或事务提交后,快照(数据库投影)向一级缓存看齐而修改数据;