Session.get/load的区别:
      1.如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObejctNotFoundException。
      2.Load方法可返回实体的代理类类型,而get方法永远直接返回实体类。
      3.Load方法可以充分利用内部缓存和二级缓存中现有数据,而get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取。

 

 



      Session.find/iterate的区别:
      find方法将执行Select SQL从数据库中获得所有符合条件的记录并构造相应的实体对象,实体对象构建完毕之后,就将其纳入缓存。它对缓存只写不读,因此无法利用缓存。
      iterate方法首先执行一条Select SQL以获得所有符合查询条件的数据id,随即,iterate方法首先在本地缓存中根据id查找对应的实体对象是否存在,如果缓存中已经存在对应的数据,则直接以此数据对象作为查询结果,如果没有找到,再执行相应的Select语句获得对应的库表记录(iterate方法如果执行了数据库读取操作并构建了完整的数据对象,也会将其查询结果纳入缓存)。


[实际的情况是,如果使用了iterate方法返回Iterator类型的查询结果,那么你一旦关闭session,Iterator中的数据立即就会消失.而通过find得到的List则不会如此,我想大部分人的使用习惯都是操作完成后立即关闭session,很多公司也强制要求这样做.
Iterator的另一个麻烦事是fail-fast,在多线程环境下,很容易产生.使用线程安全的List子类,则不会有这个问题]

 

 



      Query Cache产生作用的情况:
      1.完全相同的Select SQL重复执行。
      2.在两次查询之间,此Select SQL对应的库表没有发生过改变。

 

 



      Session.save方法的执行步骤:
      1.在Session内部缓存中寻找待保存对象。内部缓存命中,则认为此数据已经保存(执行过insert操作),实体对象已经处于Persistent状态,直接返回。
      2.如果实体类实现了lifecycle接口,则调用待保存对象的onSave方法。
      3.如果实体类实现了validatable接口,则调用其validate()方法。
      4.调用对应拦截器的Interceptor.onSave方法(如果有的话)。
      5.构造Insert SQL,并加以执行。
      6.记录插入成功,user.id属性被设定为insert操作返回的新记录id值。
      7.将user对象放入内部缓存。
      8.最后,如果存在级联关系,对级联关系进行递归处理。

 

 



      Session.update方法的执行步骤:
      1.根据待更新实体对象的Key,在当前session的内部缓存中进行查找,如果发现,则认为当前实体对象已经处于Persistent状态,返回。
      2.初始化实体对象的状态信息(作为之后脏数据检查的依据),并将其纳入内部缓存。注意这里Session.update方法本身并没有发送Update SQL完成数据更新操作,Update SQL将在之后的Session.flush方法中执行,根据id更新所有的字段,如update user set name=?, password=? where id=?。

 

 


 

      Session.saveOrUpdate方法的执行步骤:
      1.首先在Session内部缓存中进行查找,如果发现则直接返回。
      2.执行实体类对应的Interceptor.isUnsaved方法(如果有的话),判断对象是否为未保存状态。
      3.根据unsaved-value判断对象是否处于未保存状态。
      4.如果对象未保存(Transient状态),则调用save方法保存对象。
      5.如果对象为已保存(Detached状态),调用update方法将对象与Session重新关联。



Session.delete(E)
 E 由持久状态/游离状态 -->>自由状态



Session.flush()

调用flush
1.直接调用Session.flush();
2.tx.commit();
//flush before commiting the transaction and closing the session
//Flushing is the process of synchronising the underlying persistent store with persistable state held in memory.



E1=Session.merge(E)
if E is transient instance,则insert数据库,E状态不变化,E1是一个持久化对象;
if E is detached instance,则重新load,变成persistent instance;
if E is persistent instance,则从缓存中选择;

// Copy   the   state   of   the   given   object   onto   the   persistent   object   with   the   same   identifier.  
// If   there   is   no   persistent   instance   currently   associated   with   the   session,  it  will   be   loaded.   Return   the   persistent   instance.  
// If   the   given   instance   is   unsaved,   save   a   copy   of   and   return   it   as   a   newly   persistent   instance.   The   given   instance   does   not   become   associated   with   the   session.  
// This   operation   cascades   to   associated   instances   if   the   association   is   mapped   with   cascade="merge".



 Session.persist(E)

persist() is well defined. It makes a transient instance persistent. However,
it doesn't guarantee that the identifier value will be assigned to the persistent
instance immediately, the assignment might happen at flush time. The spec doesn't say
that, which is the problem I have with persist().

persist() also guarantees that it will not execute an INSERT statement if it is
called outside of transaction boundaries. This is useful in long-running conversations
with an extended Session/persistence context.A method like persist() is required.

save() does not guarantee the same, it returns an identifier, and if an INSERT
has to be executed to get the identifier (e.g. "identity" generator, not "sequence"),
this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context."