- 浏览: 361007 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
willsonbin:
赞~实用
表格行记录动态增加和删除 -
ljj1160347188:
/偷笑 楼主 你欺负我们这些新学的么
java的转义字符 -
zx5191:
啥jb玩意啊
java的转义字符 -
hyde12:
楼主要严谨点
java的转义字符 -
iteeye:
楼主要严谨点
java的转义字符
首先看看中文翻译的Hibernate的Session的javadoc
Interface Session
All Superinterfaces:
Serializable
All Known Subinterfaces:
EventSource, Session
All Known Implementing Classes:
SessionImpl
public interface Session extends Serializable
Java应用程序与Hibernate之间的主要运行时接口。它是抽象了持久化服务概念的核心抽象API类。
Session的生命周期绑定在一个物理的事务(tansaction)上面。(长的事务可能跨越多个数据库事物。)
Session的主要功能是提供对映射的实体类实例的创建,读取和删除操作。
实例可能以下面三种状态存在:
瞬态或者自由态(transient): 不曾进行持久化,未与任何Session相关联
持久化状态(persistent): 仅与一个Session相关联
脱管状态或者游离态(detached): 已经进行过持久化,但当前未与任何Session相关联
游离状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。
持久化实例可以通过调用 delete()变成游离状态。
通过get()或load()方法得到的实例都是持久化状态的。
游离状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。
游离或者自由状态下的实例可以通过调用merge()方法成为一个新的持久化实例。
save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,而update()或merge()会引发SQLUPDATE。
对持久化(persistent)实例的修改在刷新提交的时候会被检测到,它也会引起SQLUPDATE。
saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE。
其具体实现并不一定是线程安全的。每个线程/事务应该从一个SessionFactory获取自己的session实例。
如果其持久化对象类是可序列化的,则Session实例也是可序列化的。
一个典型的事务应该使用下面的形式:
如果Session抛出了异常, 事务必须回滚而session会被废弃。在异常发生后Session的内部状态可能会与数据库失去同步。
save方法
public Serializable save(Object object)
throws HibernateException
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".
持久化指定的游离态对象,首先要分配一个自动生成的主键标示符。
(或者如果主键生成器正在使用,使用当前主键标示符属性值)
如果关联关系映射配置了cascade="save-update"属性,save操作对关联对象级联操作。
Parameters:
object - a transient instance of a persistent class
一个要持久化类的自由状态的实例对象
Returns:
the generated identifier
返回生成的主键标示符
Throws:
HibernateException
实例:
Session.save()方法用于实体对象的持久化保存,也就是说当执行session.save()方法时会生成对应的insert SQL语句,完成数据的保存。
如下面的代码:
当执行到session.save()方法时,Hibernate并不会马上生成insert SQL语句来进行数据的保存,而是当稍后清理session的缓存时才有可能执行insert SQL语句,那么session.save()方法到底会执行哪些步骤呢?
Hibernate3.2中save()方法实现的源代码:
持久化指定的游离态对象,首先要分配一个自动生成的主键标示符。(或者如果主键生成器正在使用,使用当前主键标示符属性值)
update方法
public void update(Object object)
throws HibernateException
Update the persistent instance with the identifier of the given detached instance.
If there is a persistent instance with the same identifier, an exception is thrown.
This operation cascades to associated instances if the association is mapped with cascade="save-update".
使用给定的游离状态对象的主键标示符来更新持久化状态实例对象。
如果存在相同主键标示符的持久化状态对象,抛出异常。
如果关联关系映射配置了cascade="save-update"属性,update操作对关联对象级联操作。
Parameters:
object - a detached instance containing updated state
包含了要更新状态的游离状态对象
Throws:
HibernateException
Hibernate3.2中update()方法实现的源代码:
实例:
前面我在实体对象状态转化部分曾经讲过,session.update()方法能够将一个处于游离状态的对象,重新纳入Hibernate的内部缓存,变成持久化对象。
如下面的代码:
那么update方法到底执行了哪些步骤呢?它会按照下面的步骤进行操作:
控制台查看Hibernate生成的sql语句如下:
Hibernate: select user0_.id as id0_0_, user0_.logon_name as logon2_0_0_, user0_.nick_name as nick3_0_0_, user0_.password as password0_0_ from logon_user user0_ where user0_.id=?
Hibernate: update logon_user set logon_name=?, nick_name=?, password=? where id=?
一、首先会在缓存中寻找需要更新的实体对象,如果找到就立刻返回,从这里我们可以看出如果对一个已经处于persistent的实体对象执行update()方法,将不会产生任何作用。
二、然后当提交事务进行缓存清理时,将会通过脏数据检查,确定变化的属性,然后生成update SQL语句完成数据的更新。
这里有一个问题我们要强调一下,那就是只要通过update()方法将一个游离对象与session相关联,那么不论这个游离的实体对象的属性是否发生改变,都会执行update SQL语句。
如下面的代码:
在这段代码中并没有修改customer对象的任何属性值,但是也会执行一个update SQL语句,如果你希望在没有改变实体对象属性值的情况下不去执行update SQL语句,那么你要开启实体对象元素的”select-before-update”属性,将其设置为”true”,这个属性默认为”false”。
如下进行配置:
如果启用了这个属性配置,那么在清理session缓存之前,会首先执行类似如下的一条SQL语句:
Select * from logon_user where id='1';
查询处所有的customer实体在数据库中对应的属性值,然后逐条与缓存中属性值进行比较,如果发生了改变,那么将会生成update操作进行数据更新,如果没有发生改变那么将不会进行update操作。
要跟据实际需求情况来决定是否开启这个选项,如果实体对象的属性不会经常发生改变,那么就应该开启这个选项,以免执行多余的update操作。如果实体对象的属性会经常发生改变,那么就没必要开启这个选项,以免在执行update操作前再执行多余的select语句。
注意事项:
1.当执行对一个游离实体对象执行session.update()操作时,如果在数据库中不存在这个实体对应的纪录,那么这个操作将会抛出异常。
2.当执行session.update()方法将一个游离对象与session关联时,如果此时在缓存中已经存在了与该实体对象具有相同OID的持久化对象,那么这个方法会抛出异常。
如下面代码:
当再次将游离对象customer1与session2关联时,此时因为load()操作,在缓存已经加载了一个和customer1具有相同OID的othercustomer对象,此时由于Hibernate缓存的对象缓存机制不允许把OID相同的对象缓存,所以会抛出异常。
load方法
public void load(Object object,
Serializable id)
throws HibernateException
Read the persistent state associated with the given identifier into the given transient instance.
读取和给定的主键标示符关联的持久化状态到给定的自由状态的实例对象。
Parameters:
object - an "empty" instance of the persistent class
id - a valid identifier of an existing persistent instance of the class
object - 一个持久化类的空对象
id - 一个已经存在的持久化实例对象的有效的主键标示符
Throws:
HibernateException
get和load方法的区别?
get和load方式是根据id取得一个记录
下边详细说一下get和load的不同,因为有些时候为了对比也会把find加进来。
1.从返回结果上对比:
load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常
get方法检索不到的话会返回null
2.从检索执行机制上对比:
get方法和find方法都是直接从数据库中检索
而load方法的执行则比较复杂
■ 首先查找session的persistent Context中是否有缓存,如果有则直接返回
■ 如果没有则判断是否是lazy,如果不是直接访问数据库检索,查到记录返回,查不到抛出异常
■ 如果是lazy则需要建立代理对象,对象的initialized属性为false,target属性为null
■ 在访问获得的代理对象的属性时,检索数据库,如果找到记录则把该记录的对象复制到代理对象的target上,并将initialized=true,如果找不到就抛出异常 。
3.根本区别说明
■ 如果你使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的,所以它可以放心的使用,它可以放心的使用代理来延迟加载该对象。在用到对象中的其他属性数据时才查询数据库,但是万一数据库中不存在该记录,那没办法,只能抛异常。所说的load方法抛异常是指在使用该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时(注意:这就是由于“延迟加载”在作怪)。
由于session中的缓存对于hibernate来说是个相当廉价的资源,所以在load时会先查一下session缓存看看该id对应的对象是否存在,不存在则创建代理。所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载。
■ 对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null。
对于load和get方法返回类型:虽然好多书中都这么说:“get()永远只返回实体类”,但实际上这是不正确的,get方法如果在session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象,如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。
get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。
4.简单总结
总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。
saveOrUpdate方法
public void saveOrUpdate(Object object)
throws HibernateException
Either save(Object) or update(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".
可能对给定的实例对象执行save或者update方法,如果关联关系映射配置了cascade="save-update"属性,update操作对关联对象级联操作。
Parameters:
object - a transient or detached instance containing new or updated state
object - 包含新的或者已更新状态的自由态或者是游离态的
对象实例
Throws:
HibernateException
See Also:
save(Object), update(Object)
Hibernate3.2中saveOrUpdate()方法实现的源代码:
查看onSaveOrUpdate(event)方法的定义:
这个方法包含了save()方法和update()方法的特点,如果传入该方法的是一个游离对象,那么这个方法就会执行update操作,如果传入该方法的是一个自由对象,那么这个方法就会执行insert操作。
这个方法幕后的工作原理如下:
1.首先在缓存寻找,如果找到待保存的操作就直接返回。
2.如果实体实现了拦截方法,那么就执行isUnsaved()方法,判断实体对象状态。
3.如果实体处于自由状态就执行save(),如果实体处于游离状态那么就执行update()。
这里存在一个问题,那就是Hibernate是怎样判断一个实体是处于游离态还是临时状态的?
如果实体满足下面的一个条件,就认为这个实体处于临时状态。
Java对象的OID值为null。
1.如果Java对象具有version属性(可以了解并发加锁部分)且为null。
2.如果实体的设置了属性unsaved-value,而且OID值与unsaved-value值相等。
3.如果实体的version属性设置了unsaved-value,并且version属性的值与unsaved-value值相等。
4.如果实体实现了Interceptor,而且Interceptor.isUnsaved()方法返回true。
满足这些条件中的一个,这个实体就被认为是临时对象。
Session.delete()方法:
delete()方法用于从数据库中删除一个或一批实体所对应的数据,如果传入的对象是持久化对象,那么当清理缓存时,就会执行delete操作。
如果传入的是游离对象,那么首先会使该对象与session相关联,然后当清理缓存时,再执行delete操作。
看如下代码:
如果上面的代码中的customer对象是一个游离对象,那么当执行session.delete()方法时,会首先将游离的customer对象与session相关联(转换为持久态),然后再清理缓存时,再执行delete操作。
如果你想一次删除多条数据,那么可以采用一个重载的delete()方法:delete("from Customer c where c.id > '8'");这个方法可以删除符合条件的所有数据。
Interface Session
All Superinterfaces:
Serializable
All Known Subinterfaces:
EventSource, Session
All Known Implementing Classes:
SessionImpl
public interface Session extends Serializable
Java应用程序与Hibernate之间的主要运行时接口。它是抽象了持久化服务概念的核心抽象API类。
Session的生命周期绑定在一个物理的事务(tansaction)上面。(长的事务可能跨越多个数据库事物。)
引用
Session的主要功能是提供对映射的实体类实例的创建,读取和删除操作。
实例可能以下面三种状态存在:
瞬态或者自由态(transient): 不曾进行持久化,未与任何Session相关联
持久化状态(persistent): 仅与一个Session相关联
脱管状态或者游离态(detached): 已经进行过持久化,但当前未与任何Session相关联
游离状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。
持久化实例可以通过调用 delete()变成游离状态。
通过get()或load()方法得到的实例都是持久化状态的。
游离状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。
游离或者自由状态下的实例可以通过调用merge()方法成为一个新的持久化实例。
save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,而update()或merge()会引发SQLUPDATE。
对持久化(persistent)实例的修改在刷新提交的时候会被检测到,它也会引起SQLUPDATE。
saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE。
其具体实现并不一定是线程安全的。每个线程/事务应该从一个SessionFactory获取自己的session实例。
如果其持久化对象类是可序列化的,则Session实例也是可序列化的。
一个典型的事务应该使用下面的形式:
Session sess = factory.openSession(); Transaction tx; try { tx = sess.beginTransaction(); //do some work ... tx.commit(); } catch (Exception e) { if (tx!=null) tx.rollback(); throw e; } finally { sess.close(); }
如果Session抛出了异常, 事务必须回滚而session会被废弃。在异常发生后Session的内部状态可能会与数据库失去同步。
引用
save方法
public Serializable save(Object object)
throws HibernateException
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".
持久化指定的游离态对象,首先要分配一个自动生成的主键标示符。
(或者如果主键生成器正在使用,使用当前主键标示符属性值)
如果关联关系映射配置了cascade="save-update"属性,save操作对关联对象级联操作。
Parameters:
object - a transient instance of a persistent class
一个要持久化类的自由状态的实例对象
Returns:
the generated identifier
返回生成的主键标示符
Throws:
HibernateException
实例:
Session.save()方法用于实体对象的持久化保存,也就是说当执行session.save()方法时会生成对应的insert SQL语句,完成数据的保存。
如下面的代码:
public static void insertUser() { Session sess = HibernateSessionFactory.getSession(); User user = new User(); Transaction tx = null; try { tx = sess.beginTransaction(); // do some work user.setLogonName("关羽"); user.setNickName("关云长"); user.setPassword("1234"); sess.save(user); tx.commit(); } catch (Exception e) { if (tx != null) tx.rollback(); } finally { sess.close(); } }
当执行到session.save()方法时,Hibernate并不会马上生成insert SQL语句来进行数据的保存,而是当稍后清理session的缓存时才有可能执行insert SQL语句,那么session.save()方法到底会执行哪些步骤呢?
Hibernate3.2中save()方法实现的源代码:
引用
/** * Concrete implementation of a Session, and also the central, organizing component * of Hibernate's internal implementation. As such, this class exposes two interfaces; * Session itself, to the application, and SessionImplementor, to other components * of Hibernate. This class is not threadsafe. * * @author Gavin King */ public final class SessionImpl extends AbstractSessionImpl implements EventSource, org.hibernate.classic.Session, JDBCContext.Context { //省略部分代码 // save() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public void save(Object obj, Serializable id) throws HibernateException { save(null, obj, id); } public Serializable save(Object obj) throws HibernateException { return save(null, obj); } public Serializable save(String entityName, Object object) throws HibernateException { return fireSave( new SaveOrUpdateEvent(entityName, object, this) ); } public void save(String entityName, Object object, Serializable id) throws HibernateException { fireSave( new SaveOrUpdateEvent(entityName, object, id, this) ); } private Serializable fireSave(SaveOrUpdateEvent event) { errorIfClosed(); checkTransactionSynchStatus(); SaveOrUpdateEventListener[] saveEventListener = listeners.getSaveEventListeners(); for ( int i = 0; i < saveEventListener.length; i++ ) { saveEventListener[i].onSaveOrUpdate(event); } return event.getResultId(); } //省略部分代码 }
持久化指定的游离态对象,首先要分配一个自动生成的主键标示符。(或者如果主键生成器正在使用,使用当前主键标示符属性值)
引用
请看进行了如下总结:
一、在session的内部缓存中寻找保存对象,如果找到了,则认为此数据已经保存(曾经执行过insert操作),实体对象已经处于persistent状态,直接返回。此时即使数据相比之前的状态发生了变化,也将在事务提交时由脏数据检查来判定是否需要执行update操作。
二、如果实体对象实现了lifecycle接口,那么将执行待保存对象的onSave()方法。
三、如果实体对象实现了Validatable接口,那么将会执行相应的validate()方法。
四、如果存在拦截器对象,那么将会执行Interceptor.onSave()方法。
五、构造insert SQL语句完成数据保存。
六、数据保存成功后,设定实体对象的id为插入记录的id。
七、将保存后的实体对象纳入Hibernate的内部缓存(一级缓存)。注意Hibernate不会把保存后的实体对象纳入二级缓存,因为刚刚保存过的实体对象很可能在之后被修改,缓存的频繁更新以及带来的同步问题代价,超出了缓存该对象所带来的收益。
八、如果关联关系映射配置了cascade="save-update"属性,save操作对关联对象级联操作。
一、在session的内部缓存中寻找保存对象,如果找到了,则认为此数据已经保存(曾经执行过insert操作),实体对象已经处于persistent状态,直接返回。此时即使数据相比之前的状态发生了变化,也将在事务提交时由脏数据检查来判定是否需要执行update操作。
二、如果实体对象实现了lifecycle接口,那么将执行待保存对象的onSave()方法。
三、如果实体对象实现了Validatable接口,那么将会执行相应的validate()方法。
四、如果存在拦截器对象,那么将会执行Interceptor.onSave()方法。
五、构造insert SQL语句完成数据保存。
六、数据保存成功后,设定实体对象的id为插入记录的id。
七、将保存后的实体对象纳入Hibernate的内部缓存(一级缓存)。注意Hibernate不会把保存后的实体对象纳入二级缓存,因为刚刚保存过的实体对象很可能在之后被修改,缓存的频繁更新以及带来的同步问题代价,超出了缓存该对象所带来的收益。
八、如果关联关系映射配置了cascade="save-update"属性,save操作对关联对象级联操作。
引用
update方法
public void update(Object object)
throws HibernateException
Update the persistent instance with the identifier of the given detached instance.
If there is a persistent instance with the same identifier, an exception is thrown.
This operation cascades to associated instances if the association is mapped with cascade="save-update".
使用给定的游离状态对象的主键标示符来更新持久化状态实例对象。
如果存在相同主键标示符的持久化状态对象,抛出异常。
如果关联关系映射配置了cascade="save-update"属性,update操作对关联对象级联操作。
Parameters:
object - a detached instance containing updated state
包含了要更新状态的游离状态对象
Throws:
HibernateException
Hibernate3.2中update()方法实现的源代码:
引用
/** * Concrete implementation of a Session, and also the central, organizing component * of Hibernate's internal implementation. As such, this class exposes two interfaces; * Session itself, to the application, and SessionImplementor, to other components * of Hibernate. This class is not threadsafe. * * @author Gavin King */ public final class SessionImpl extends AbstractSessionImpl implements EventSource, org.hibernate.classic.Session, JDBCContext.Context { //省略部分代码 // update() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public void update(Object obj) throws HibernateException { update(null, obj); } public void update(Object obj, Serializable id) throws HibernateException { update(null, obj, id); } public void update(String entityName, Object object) throws HibernateException { fireUpdate( new SaveOrUpdateEvent(entityName, object, this) ); } public void update(String entityName, Object object, Serializable id) throws HibernateException { fireUpdate(new SaveOrUpdateEvent(entityName, object, id, this)); } private void fireUpdate(SaveOrUpdateEvent event) { errorIfClosed(); checkTransactionSynchStatus(); SaveOrUpdateEventListener[] updateEventListener = listeners.getUpdateEventListeners(); for ( int i = 0; i < updateEventListener.length; i++ ) { updateEventListener[i].onSaveOrUpdate(event); } } //省略部分代码 }
实例:
前面我在实体对象状态转化部分曾经讲过,session.update()方法能够将一个处于游离状态的对象,重新纳入Hibernate的内部缓存,变成持久化对象。
如下面的代码:
Configuration cfg = new Configuration(); SessionFactory sf=cfg. configure().buildSessionFactory(); Customer customer=new Customer("关羽",27);//customer对象处于自由状态 Session session=sf.openSession(); // 开启事务 Transaction tx=session.beginTransaction(); //保存后customer对象处于持久化状态 session.save(customer); //清空缓存后customer对象处于游离状态 session.flush(); // 提交事务 tx.commit(); //session关闭 session.close(); // 又开启一个新的session Session session2=sf.openSession(); Transaction tx2=session2.beginTransaction(); //通过调用update()方法将游离状态的customer对象,再次转化成持久化状态 session2.update(customer); //调用delete()方法后,当清空缓存时,会将customer对象移出缓存,同时会在数据库中生成delete事务,来删除customer对象对应的数据记录 session2.delete(customer); tx.commit(); session.close();
那么update方法到底执行了哪些步骤呢?它会按照下面的步骤进行操作:
引用
控制台查看Hibernate生成的sql语句如下:
Hibernate: select user0_.id as id0_0_, user0_.logon_name as logon2_0_0_, user0_.nick_name as nick3_0_0_, user0_.password as password0_0_ from logon_user user0_ where user0_.id=?
Hibernate: update logon_user set logon_name=?, nick_name=?, password=? where id=?
一、首先会在缓存中寻找需要更新的实体对象,如果找到就立刻返回,从这里我们可以看出如果对一个已经处于persistent的实体对象执行update()方法,将不会产生任何作用。
二、然后当提交事务进行缓存清理时,将会通过脏数据检查,确定变化的属性,然后生成update SQL语句完成数据的更新。
这里有一个问题我们要强调一下,那就是只要通过update()方法将一个游离对象与session相关联,那么不论这个游离的实体对象的属性是否发生改变,都会执行update SQL语句。
如下面的代码:
Transaction tx=session.beginTransaction(); session.update(customer); tx.commit(); session.close();
在这段代码中并没有修改customer对象的任何属性值,但是也会执行一个update SQL语句,如果你希望在没有改变实体对象属性值的情况下不去执行update SQL语句,那么你要开启实体对象元素的”select-before-update”属性,将其设置为”true”,这个属性默认为”false”。
如下进行配置:
如果启用了这个属性配置,那么在清理session缓存之前,会首先执行类似如下的一条SQL语句:
Select * from logon_user where id='1';
查询处所有的customer实体在数据库中对应的属性值,然后逐条与缓存中属性值进行比较,如果发生了改变,那么将会生成update操作进行数据更新,如果没有发生改变那么将不会进行update操作。
要跟据实际需求情况来决定是否开启这个选项,如果实体对象的属性不会经常发生改变,那么就应该开启这个选项,以免执行多余的update操作。如果实体对象的属性会经常发生改变,那么就没必要开启这个选项,以免在执行update操作前再执行多余的select语句。
注意事项:
1.当执行对一个游离实体对象执行session.update()操作时,如果在数据库中不存在这个实体对应的纪录,那么这个操作将会抛出异常。
2.当执行session.update()方法将一个游离对象与session关联时,如果此时在缓存中已经存在了与该实体对象具有相同OID的持久化对象,那么这个方法会抛出异常。
如下面代码:
Customer customer1=new Customer("刘备",25); Session session1=sf.openSession(); Transaction tx=session1.beginTransaction(); //保存后customer对象处于持久化状态 session.save(customer1); //清空缓存后customer对象处于游离状态 session.flush(); tx.commit(); session1.close(); Session session2=sf.openSession(); Transaction tx2=session2.beginTransaction(); Customer othercustomer=(Customer)session2.load(Customer.class,"1"); //通过调用update()方法将游离状态的customer1对象,再次转化成持久化状态 session2.update(customer1) tx2.commit(); session2.close();
当再次将游离对象customer1与session2关联时,此时因为load()操作,在缓存已经加载了一个和customer1具有相同OID的othercustomer对象,此时由于Hibernate缓存的对象缓存机制不允许把OID相同的对象缓存,所以会抛出异常。
引用
load方法
public void load(Object object,
Serializable id)
throws HibernateException
Read the persistent state associated with the given identifier into the given transient instance.
读取和给定的主键标示符关联的持久化状态到给定的自由状态的实例对象。
Parameters:
object - an "empty" instance of the persistent class
id - a valid identifier of an existing persistent instance of the class
object - 一个持久化类的空对象
id - 一个已经存在的持久化实例对象的有效的主键标示符
Throws:
HibernateException
引用
get和load方法的区别?
get和load方式是根据id取得一个记录
下边详细说一下get和load的不同,因为有些时候为了对比也会把find加进来。
1.从返回结果上对比:
load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常
get方法检索不到的话会返回null
2.从检索执行机制上对比:
get方法和find方法都是直接从数据库中检索
而load方法的执行则比较复杂
■ 首先查找session的persistent Context中是否有缓存,如果有则直接返回
■ 如果没有则判断是否是lazy,如果不是直接访问数据库检索,查到记录返回,查不到抛出异常
■ 如果是lazy则需要建立代理对象,对象的initialized属性为false,target属性为null
■ 在访问获得的代理对象的属性时,检索数据库,如果找到记录则把该记录的对象复制到代理对象的target上,并将initialized=true,如果找不到就抛出异常 。
3.根本区别说明
■ 如果你使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的,所以它可以放心的使用,它可以放心的使用代理来延迟加载该对象。在用到对象中的其他属性数据时才查询数据库,但是万一数据库中不存在该记录,那没办法,只能抛异常。所说的load方法抛异常是指在使用该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时(注意:这就是由于“延迟加载”在作怪)。
由于session中的缓存对于hibernate来说是个相当廉价的资源,所以在load时会先查一下session缓存看看该id对应的对象是否存在,不存在则创建代理。所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载。
■ 对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null。
对于load和get方法返回类型:虽然好多书中都这么说:“get()永远只返回实体类”,但实际上这是不正确的,get方法如果在session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象,如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。
get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。
4.简单总结
总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。
引用
saveOrUpdate方法
public void saveOrUpdate(Object object)
throws HibernateException
Either save(Object) or update(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".
可能对给定的实例对象执行save或者update方法,如果关联关系映射配置了cascade="save-update"属性,update操作对关联对象级联操作。
Parameters:
object - a transient or detached instance containing new or updated state
object - 包含新的或者已更新状态的自由态或者是游离态的
对象实例
Throws:
HibernateException
See Also:
save(Object), update(Object)
Hibernate3.2中saveOrUpdate()方法实现的源代码:
引用
/** * Concrete implementation of a Session, and also the central, organizing component * of Hibernate's internal implementation. As such, this class exposes two interfaces; * Session itself, to the application, and SessionImplementor, to other components * of Hibernate. This class is not threadsafe. * * @author Gavin King */ public final class SessionImpl extends AbstractSessionImpl implements EventSource, org.hibernate.classic.Session, JDBCContext.Context { //省略部分代码 // saveOrUpdate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public void saveOrUpdate(Object object) throws HibernateException { saveOrUpdate(null, object); } public void saveOrUpdate(String entityName, Object obj) throws HibernateException { fireSaveOrUpdate( new SaveOrUpdateEvent(entityName, obj, this) ); } private void fireSaveOrUpdate(SaveOrUpdateEvent event) { errorIfClosed(); checkTransactionSynchStatus(); SaveOrUpdateEventListener[] saveOrUpdateEventListener = listeners.getSaveOrUpdateEventListeners(); for ( int i = 0; i < saveOrUpdateEventListener.length; i++ ) { saveOrUpdateEventListener[i].onSaveOrUpdate(event); } } //省略部分代码 }
查看onSaveOrUpdate(event)方法的定义:
public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener implements SaveOrUpdateEventListener { private static final Log log = LogFactory.getLog( DefaultSaveOrUpdateEventListener.class ); /** * Handle the given update event. * * @param event The update event to be handled. */ public void onSaveOrUpdate(SaveOrUpdateEvent event) { final SessionImplementor source = event.getSession(); final Object object = event.getObject(); final Serializable requestedId = event.getRequestedId(); if ( requestedId != null ) { //assign the requested id to the proxy, *before* //reassociating the proxy if ( object instanceof HibernateProxy ) { ( ( HibernateProxy ) object ).getHibernateLazyInitializer().setIdentifier( requestedId ); } } if ( reassociateIfUninitializedProxy( object, source ) ) { log.trace( "reassociated uninitialized proxy" ); // an uninitialized proxy, noop, don't even need to // return an id, since it is never a save() } else { //initialize properties of the event: final Object entity = source.getPersistenceContext().unproxyAndReassociate( object ); event.setEntity( entity ); event.setEntry( source.getPersistenceContext().getEntry( entity ) ); //return the id in the event object event.setResultId( performSaveOrUpdate( event ) ); } } // 省略部分代码... ... }
这个方法包含了save()方法和update()方法的特点,如果传入该方法的是一个游离对象,那么这个方法就会执行update操作,如果传入该方法的是一个自由对象,那么这个方法就会执行insert操作。
这个方法幕后的工作原理如下:
1.首先在缓存寻找,如果找到待保存的操作就直接返回。
2.如果实体实现了拦截方法,那么就执行isUnsaved()方法,判断实体对象状态。
3.如果实体处于自由状态就执行save(),如果实体处于游离状态那么就执行update()。
这里存在一个问题,那就是Hibernate是怎样判断一个实体是处于游离态还是临时状态的?
如果实体满足下面的一个条件,就认为这个实体处于临时状态。
Java对象的OID值为null。
1.如果Java对象具有version属性(可以了解并发加锁部分)且为null。
2.如果实体的设置了属性unsaved-value,而且OID值与unsaved-value值相等。
3.如果实体的version属性设置了unsaved-value,并且version属性的值与unsaved-value值相等。
4.如果实体实现了Interceptor,而且Interceptor.isUnsaved()方法返回true。
满足这些条件中的一个,这个实体就被认为是临时对象。
Session.delete()方法:
delete()方法用于从数据库中删除一个或一批实体所对应的数据,如果传入的对象是持久化对象,那么当清理缓存时,就会执行delete操作。
如果传入的是游离对象,那么首先会使该对象与session相关联,然后当清理缓存时,再执行delete操作。
看如下代码:
Session session=sessionFactory().openSession(); Transaction tx=session.beginTransaction(); //加载持久态对象 Customer customer=(Customer)session.load(Customer.class,”1”); //计划执行一条delete语句 session.delete(customer); //清理缓存,执行一条delete语句 tx.commit(); //关闭session,这时将会把customer对象从缓存中删除 session.close();
如果上面的代码中的customer对象是一个游离对象,那么当执行session.delete()方法时,会首先将游离的customer对象与session相关联(转换为持久态),然后再清理缓存时,再执行delete操作。
如果你想一次删除多条数据,那么可以采用一个重载的delete()方法:delete("from Customer c where c.id > '8'");这个方法可以删除符合条件的所有数据。
相关推荐
对象持久化是将内存中的数据保存在永久存储介质——数据库中,以防止断电或网络传输时数据丢失。主要有以下原因促使我们进行数据持久化:内存的临时性,数据传输的限制,数据组织和查询的不便,以及内存容量的限制。...
3. Session和Transaction管理:阐述了Hibernate的核心接口Session的使用,包括打开、关闭、保存、更新、删除对象的方法。同时,讲解了事务(Transaction)管理的基础知识,如何确保数据操作的原子性、一致性、隔离性...
本文将详细介绍 Hibernate 中常用的几种方法,包括 `save`, `update`, `saveOrUpdate`, `merge` 等,帮助开发者更深入地理解 Hibernate 的工作原理及其使用方式。 #### 二、Hibernate 对象状态管理 在 Hibernate ...
4. **Session接口**:Session是Hibernate与数据库交互的主要接口,它负责管理对象的状态,提供了保存、更新、删除和查询对象的方法。理解Session的工作原理和生命周期对于优化性能至关重要。 5. **Criteria查询**:...
1. Session接口:它是Hibernate的核心接口,提供了对持久化对象的操作,如保存、更新、删除和加载。通过SessionFactory创建Session实例,进而执行数据库操作。 2. Configuration类:负责读取hibernate.cfg.xml配置...
Hibernate是一个开源的对象关系映射(ORM)框架,它简化了Java应用与数据库之间的交互,通过提供一种在Java对象和数据库记录之间建立映射关系的方法,使得开发者无需编写大量的SQL语句,就可以实现对数据库的操作。...
- **Hibernate**:非常成熟且功能强大的ORM框架,支持面向对象的数据操作,消除了特定数据库厂商的SQL代码依赖。 - **MyBatis**:相比Hibernate更为灵活,运行速度更快,但需要熟悉SQL语句并进行优化。 - **TopLink*...
2. **Persistence Manager(持久化管理器)**:是JDO的核心组件,负责对象的持久化操作,如保存、删除、查询等。 3. **Object Identity(对象标识)**:每个持久化对象都有唯一的标识,即使对象在内存中被复制,其...
- **对象持久化**:使用Hibernate API来保存、更新、删除Java对象,Hibernate会自动将这些操作转换为相应的SQL语句。 - **查询**:支持多种查询方式,如HQL(Hibernate Query Language)、Criteria API等。 ### ...
Hibernate工作原理,Hibernate数据持久化? 答:Hibernate工作原理: 1:读取并解析映射信息,创建SessionFactory 2:打开Session 3:创建事物 4:持久化操作 5:提交事务 6:关闭Session 7:关闭...
此外,系统还引入了Hibernate框架,这是一款流行的Java持久层解决方案,用于简化数据库操作,提高数据访问效率。 ##### 2.2 架构设计 系统设计遵循模块化原则,采用面向对象的方法进行构建。模块化设计使得各功能...
- **操作持久化对象**:演示如何使用Hibernate API来保存、更新、删除和检索对象。 - **事务,并发**:探讨如何在Hibernate中管理事务,并解决并发问题。 - **高级映射概念**:介绍更复杂的映射策略,如继承映射和...
- **概述数据模型**:数据模型是描述数据的结构、关系以及操作规则的一种方法,常见的有ER模型等。 - **数据库设计**:包括需求分析、概念设计、逻辑设计和物理设计等多个阶段。 **3. 创建表** - 使用`CREATE TABLE...
通过配置文件或注解,它可以自动将数据库记录映射到Java对象,或者将Java对象的数据保存到数据库中,大大减少了手动编写SQL和DAO接口实现的工作量。 ### 2. S2dao的主要特点 - **简单易用**:S2dao的API设计简洁,...
- **实现原理**:volatile变量的读写操作会被编译器插入内存屏障,禁止指令重排序。 - **注意事项**:仅保证可见性和有序性,不保证原子性。 #### 二、并发与多线程 1. **创建线程的方式** - 继承`Thread`类 -...
MyBatis框架原理与Hibernate对比 - **MyBatis原理**: - **定义**:MyBatis是一个支持普通SQL查询、存储过程以及高级映射的优秀持久层框架。 - **特点**: - **SQL与Java代码分离**:通过XML配置文件或注解将...
**1.5 Linux相关命令操作** - **基本命令**:ls、cd、mv、cp等。 - **文件权限管理**:chmod、chown等。 - **进程管理**:ps、kill等。 - **网络工具**:netstat、telnet、wget等。 **1.6 工厂模式** - **简单...