【引用】http://davidwei05951983.spaces.live.com/Blog/cns!BED3D557991594B3!812.entry
session的常用基本操作有:
Transient instances may be made persistent by calling save(),persist() or saveOrUpdate(). Persistent instances may be made transient by calling delete(). Any instance returned by a get() or load() method is persistent. Detached instances may be made persistent by calling update(), saveOrUpdate(), lock() or replicate(). The state of a transient or detached instance may also be made persistent as a new persistent instance by calling merge().save() and persist() result in an SQL INSERT, delete() in an SQL DELETE and update() or merge() in an SQL UPDATE. Changes to persistent instances are detected at flush time and also result in an SQL UPDATE. saveOrUpdate() and replicate() result in either an INSERT or an UPDATE.
persist():
Make a transient instance persistent. This operation cascades to associated instances if the association is mapped with cascade="persist". The semantics of this method are defined by JSR-220.
当级联风格为persist时,这个操作会级联操作关联的对象。这个方法的语义是JSR-220定义的。
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."
save():
Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned generator is used.) This operation cascades to associated instances if the association is mapped with cascade="save-update".
首先会赋予一个标志符,然后持久化给定的对象。但是如果使用assigned 标志符产生方法,则会使用当前的标志符值。如果级联风格为save-pdate,则会持久化相应的关联对象.
merge():
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". The semantics of this method are defined by JSR-220.
拷贝当前的对象的状态到相同标志符的持久化对象的状态。如果当前关联的session中没有持久化对象,Hibernate会加载该对象,并返回这个持久化对象。如果给定的对象没有保存,则Hibernate保存该副本,返回这个新持久化的对象,但给定的对象并没有和session关联。如果指定级联风格为merge,则会级联关联对象。该方法的语义是JSR-200定义的。
saveOrUpdate():
Either {@link #save(String, Object)} or {@link #update(String, Object)} the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking). This operation cascades to associated instances if the association is mapped with cascade="save-update".
保存或更新给定对象,取决于给定对象的持久化状态。默认情况下是保存,在指定标志符元素属性为unsaved-value时则会调整。如果级联风格为"save-update",则会级联相关联的对象
delete():
Remove a persistent instance from the datastore. The object argument may be an instance associated with the receiving Session or a transient instance with an identifier associated with existing persistent state. This operation cascades to associated instances if the association is mapped with cascade="delete".
删除对象。
lock():
Obtain the specified lock level upon the given object. This may be used to perform a version check (LockMode.READ), to upgrade to a pessimistic lock (LockMode.UPGRADE), or to simply reassociate a transient instance with a session (LockMode.NONE). This operation cascades to associated instances if the association is mapped with cascade="lock".
用于对指定对象设置参数中给定的锁。如果锁为LockMode.READ,可以用来执行版本检查;如果锁为LockMode.UPGRADE则用来执行悲观锁。如果定为LockMode.NONE,则仅仅时持久化一个未持久化的对象。如果级联风格为lock,会级联相关联的对象。
refresh():
Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running sessions that span many business tasks. This method is, however, useful in certain special circumstances.For example where a database trigger alters the object state upon insert or update after executing direct SQL (eg. a mass update) in the same session after inserting a Blob or Clob.
从当前数据库中重新读取给定对象的状态。这在执行跨越多个业务任务的长时间session中优势不显著,在少数特定环境下还是有用的,例如: 插入或更新后数据库触发器更改了对象的状态。当前session中执行完原生SQL后(如批量更新)。 插入Blob或Clob对象后。
evict():
Remove this instance from the session cache. Changes to the instance will not be synchronized with the database. This operation cascades to associated instances if the association is mapped with cascade="evict".
从session的缓存中去除当前实例。执行后对象的改变将不再和数据库保持同步。当指定级联风格为'evict’时,会级联操作关联对象。我用的时候主要是用于批量操作的时候,清空缓存,防止内存紧张。
replicate():
Persist the state of the given detached instance, reusing the current identifier value. This operation cascades to associated instances if the association is mapped with cascade="replicate"
重用当前的标志符,持久化当前已经脱离session的对象的状态。具体的操作和要看参数ReplicationMode。如果是ReplicationMode.EXCEPTION,则在复制时如果有重复的行数据,则抛出异常。ReplicationMode.IGNORE则忽略异常。ReplicationMode.OVERWRITE则会覆盖掉已有行数据。ReplicationMode.LATEST_VERSION则是在有重复时使用最新的版本进行控制。
自动状态检测
Hibernate的用户曾要求一个既可自动分配新持久化标识(identifier)保存瞬时(transient)对象,又可更新/重新关联脱管(detached)实例的通用方法。 saveOrUpdate()方法实现了这个功能。 saveOrUpdate()用途和语义可能会使新用户感到迷惑。 首先,只要你没有尝试在某个session中使用来自另一session的实例,你就应该不需要使用update(), saveOrUpdate(),或merge()。有些程序从来不用些方法。
通常下面的场景会使用update()或saveOrUpdate():
程序在第一个session中加载对象
该对象被传递到表现层
对象发生了一些改动
该对象被返回到业务逻辑层
程序调用第二个session的update()方法持久这些改动
saveOrUpdate()做下面的事:
如果对象已经在本session中持久化了,不做任何事
如果另一个与本session关联的对象拥有相同的持久化标识(identifier),抛出一个异常
如果对象没有持久化标识(identifier)属性,对其调用save()
如果对象的持久标识(identifier)表明其是一个新实例化的对象,对其调用save()
如果对象是附带版本信息的(通过<version>或<timestamp>) 并且版本属性的值表明其是一个新实例化的对象,save()它。
否则update() 这个对象
merge()可非常不同:
如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例
如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例 ,最后返回该持久实例
用户给出的这个对象没有被关联到session上,它依旧是脱管的.
Session刷出(flush)
每间隔一段时间,Session会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为刷出(flush),默认会在下面的时间点执行:
a.在某些查询执行之前
b.在调用org.hibernate.Transaction.commit()的时候
c.在调用Session.flush()的时候
涉及的SQL语句会按照下面的顺序发出执行:
所有对实体进行插入的语句,其顺序按照对象执行Session.save()的时间顺序
所有对实体进行更新的语句
所有进行集合删除的语句
所有对集合元素进行删除,更新或者插入的语句
所有进行集合插入的语句
所有对实体进行删除的语句,其顺序按照对象执行Session.delete()的时间顺序
(有一个例外是,如果对象使用native方式来生成ID(持久化标识)的话,它们一执行save就会被插入。)
除非你明确地发出了flush()指令,关于Session何时会执行这些JDBC调用是完全无法保证的,只能保证它们执行的前后顺序。 当然,Hibernate保证,Query.list(..)绝对不会返回已经失效的数据,也不会返回错误数据。
也可以改变默认的设置,来让刷出(flush)操作发生的不那么频繁。 FlushMode类定义了三种不同的方式。 仅在提交时刷出(仅当Hibernate的Transaction API被使用时有效), 按照刚才说的方式刷出, 以及除非明确使用flush()否则从不刷出。 最后一种模式对于那些需要长时间保持Session为打开或者断线状态的长时间运行的工作单元很有用。
父子关系的级联(cascading)操作准确语义如下:
如果父对象被persist(),那么所有子对象也会被persist()
如果父对象被merge(),那么所有子对象也会被merge()
如果父对象被save(),update()或 saveOrUpdate(),那么所有子对象则会被saveOrUpdate()
如果某个持久的父对象引用了瞬时(transient)或者脱管(detached)的子对象,那么子对象将会被saveOrUpdate()
如果父对象被删除,那么所有子对象也会被delete()
除非被标记为cascade="delete-orphan"(删除“孤儿”模式,此时不被任何一个父对象引用的子对象会被删除), 否则子对象失掉父对象对其的引用时,什么事也不会发生。 如果有特殊需要,应用程序可通过显式调用delete()删除子对象。