精华内容
下载资源
问答
  • Hibernate持久化对象状态

    千次阅读 2013-07-22 09:36:55
    1、 hibernate 将持久化对象分为三种状态  transient(瞬时态、临时态) : 没有持久化标识 OID 、未与Session关联  persistent(持久态):存在持久化标识OID 、与Session关联(在事务提交 和 Session关闭...

    持久化对象 PO =  POJO + xml映射 

    1、 hibernate 将持久化对象分为三种状态

             transient(瞬时态、临时态) : 没有持久化标识 OID 、未与Session关联

             persistent(持久态):存在持久化标识OID 、与Session关联(在事务提交 和 Session关闭之前)

             detached  (脱管态、离线态) : 存在持久化标识OID ,未与Session关联


    2 、持久化对象三种状态转换


             1) 瞬时态对象:  new Book() 获得

                       瞬时 -- 持久  save()  saveOrUpdate()

                       瞬时 -- 脱管  book.setId(1) ; 为瞬时对象设置OID

             2) 持久态对象:  get() / load()  、 Query、 Criteria  从数据库查询

                       持久 -- 瞬时  delete()

                       持久 -- 脱管  close() 、evict() 、clear()

             3) 脱管态对象  无法直接获得

                       脱管 -- 瞬时  book.setId(null); 移除对象OID

                       脱管 -- 持久  update() 、saveOrUpdate() 、 lock() 过时

    3 Session缓存(一级缓存)      

    Hibernate框架中提供两级缓存 SessionFactory级别的缓存、Session级别的缓存

             SessionFactory 级别的缓存 ---- 二级缓存 (外置,需要引入第三方插件)

             Session 级别缓存 ----- 一级缓存 (内置,直接使用 )

    l  在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期

    l  当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图get()、 load()对象时,会判断缓存中是否存在该对象,有则返回,此时不查询数据库。没有再查询数据库

    l  Session 能够在某些时间点, 按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为刷出缓存(flush)

    默认情况下 Session 在以下时间点刷出缓存

    a           当应用程序调用 Transaction commit()方法的时, 该方法先刷出缓存(session.flush()),    然后在向数据库提交事务(tx.commit())

    b           当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先         刷出缓存,以保证查询结果能够反映持久化对象的最新状态

    c           调用 Session 的 flush() 方法

    hibernate快照

             当session加载了customer对象后,会为customer对象的值类型的属性复制一份快照。当刷出缓存时,     通过比较对象的当前属性和快照,来判断对象的哪些属性发生了变化

    案例: 编程证明一级缓存是存在的

                       Session session =HibernateUtils.openSession();

                       Transaction transaction =session.beginTransaction();

                       // 所有持久态对象 都会被放入一级缓存

                       Book book = (Book)session.get(Book.class, 1); // 持久态 放入缓存

                       System.out.println(book);

                       // 再次执行查询 --- 直接使用一级缓存中数据(控制台上的查询语句仍是只有一句)

                       Book book2 = (Book)session.get(Book.class, 1);

                       System.out.println(book2);

                       transaction.commit();

                       session.close();

    案例 : 快照和缓存存储原理 ,测试快照自动 flush数据

                       Session session =HibernateUtils.openSession();

                       Transaction transaction =session.beginTransaction();

                       // 先将图书查询出

                       Book book = (Book)session.get(Book.class, 1);// 持久态

                       book.setPrice(200d); // 修改一级缓存对象数据

                       // 不调用update ,是否可以更新(有transaction.commit()就有flush操作,就能更新)

                       transaction.commit(); // 如果 不flush ,数据不会改变

                       session.close();

     

    一级缓存常见操作  flush 、evict 、clear 、refresh

             * flush 比较缓存数据和快照数据是否一致,如果改变,将缓存数据更新到数据库(快照也更新,不会      清除缓存数据)

             * clear 会清除所有一级缓存数据(所有持久对象都会变为脱管对象)

             * evict 清除指定对象的一级缓存数据(被清除的对象,由持久变为脱管)

             * refresh  使用数据库中数据去覆盖缓存和快照的数据

     

    一级缓存的flush 模式  FlushMode


             * 通过session.setFlushMode 设置一级缓存刷出时间点

             * 默认FlushModel.AUTO  在 Transaction.commit  Query查询  session.flush  执行数据flush

             刷出session.flush > Transaction.commit > Query 查询

             * COMMIT  会在 session.flush和 Transaction、commit

             * MANUAL  只会在session.flush时 执行数据flush

             如果 使用MANUAL 必须 调用session.flush 才会将缓存数据更新到数据库,transaction的commit 不        会flush数据

    ALWAYS和AUTO的区别

             当hibernate缓存中的对象被改动之后,会被标记为脏数据(即与数据库不同步了)。当 session设置为         FlushMode.AUTO时,hibernate在进行查询的时候会判断缓存中的数据是否为脏数据,是则刷数据库,     不是则不刷,而always是直接刷新,不进行任何判断。很显然auto比always要高效得多

     

    4、 持久化对象的操作

             1) save 方法  瞬时态对象 转换 持久态对象

             如果采用数据库主键自增策略,执行save方法时,第一时间将insert语句发送到数据库,获得生成id ,  保存瞬时对象中,成为持久对象。持久化对象 OID 不能随意修改

             2) update 方法 将脱管变为持久

              将数据更新到数据库, 放入一级缓存

              如果脱管数据和数据库是一样的,执行update就没有意义,但是update任然会执行。如果设置select-before-update 属性,就会在修改之前先查询

    *<classname="cn.itcast.domain.Book" table="book"catalog="hibernate3day2" select-before-update="true">

              如果更新脱管对象OID 在数据库不存在,就会发生如下异常 

              * org.hibernate.StaleObjectStateException: Row was updated or deleted byanother transaction (or unsaved-value mapping was incorrect):[cn.itcast.domain.Book#3]

              如果 更新脱管对象时,一级缓存中已经存在相同OID的持久对象, 会发生异常

              * org.hibernate.NonUniqueObjectException: a different object with thesame identifier value was already associated with the session:[cn.itcast.domain.Book#2]

             3) saveOrUpdate

                       如果操作目标对象,没有OID (OIDnull OID为设置unsaved-value),执行save

                       如果操作目标对象,存在OID ,执行update

             例:在Book.hbm.xml设置 <id name="id" unsaved-value="1000"> ,如果操作Book OID1000,框架会认为Book对象是一个瞬时对象       

        4) get 、load

             get 立即执行SQL语句,返回目标对象

             load 默认采用延迟加载机制,返回目标类子类对象 (代理对象),不会立即执行SQL语句,会在访问对象内除了id之外属性时执行SQL

             如果OID在目标数据库不存在,get立即执行返回 nullload 返回代理对象,访问对象的值时,抛出异常 ObjectNotFoundException

             5) delete 删除

             可以删除一个脱管对象或者一个持久对象的,对于单表操作删除脱管对象和持久对象无区别,对于多表操作有外键处理区别

                       * 原理:先将脱管对象转换为持久对象再删除

                                                            注:被删除对象不要再使用  

    展开全文
  • hibernate持久化对象状态

    千次阅读 2015-09-23 11:51:12
    持久化对象状态: 瞬时对象(Transient Objects):使用new操作符初始化的对象不是立刻就持久化的。他们的状态是瞬时的,也就是说他们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何...

    持久化对象的状态:

    瞬时对象(Transient Objects):使用new操作符初始化的对象不是立刻就持久化的。他们的状态是瞬时的,也就是说他们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其他对象所引用),他们的状态将会丢失,并由垃圾回收机制回收。

    临时对象的特征。临时对象具有以下特征:
    (1) 不处于Session的缓存中,也可以说,不被任何一个Session实例关联。
    (2) 在数据库中没有对应的记录。

    在以下情况下,Java对象进入临时状态:
    (1) 当通过new语句刚创建了一个Java对象,它处于临时状态,此时不和数据库中的任何记录对应。
    (2) Sessiondelete()方法能使一个持久化对象或游离对象转变为临时对象。对于游离对象,delete()方法从数据库中删除与它对应的记录;对于持久化对象,delete()方法从数据库中删除与它对应的记录,并且把它从Session的缓存中删除。

    持久化对象(Persist Objects):持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的———他们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQLINSERT,UPDATEDELETE语句把内存中的状态同步到数据库中。

    持久化对象的特征。持久化对象具有以下特征:
    (1) 位于一个Session实例的缓存中,也可以说,持久化对象总是被一个Session实例关联。
    (2) 持久化对象和数据库中的相关记录对应。
    (3) Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库,在此期间如果修改了属性值只是session中对象的值会改变,并没有同步到数据库。

    Session的许多方法都能够触发Java对象进入持久化状态:
    (1) Sessionsave()方法把临时对象转变为持久化对象。
    (2) Sessionload()get()方法返回的对象总是处于持久化状态。
    (3) Sessionfind()方法返回的List集合中存放的都是持久化对象。
    (4) Sessionupdate()saveOrUpdate()lock()方法使游离对象转变为持久化对象。
    (5)当一个持久化对象关联一个临时对象,在允许级联保存的情况下,Session在清理缓存时会把这个临时对象也转变为持久化对象。

    Hibernate保证在同一个Session实例的缓存中,数据库表中的每条记录只对应惟一的持久化对象。例如对于以下代码,共创建了两个Session实例:session1session2session1session2拥有各自的缓存。在session1的缓存中,只会有惟一的OID1Customer持久化对象,在session2的缓存中,也只会有惟一的OID2Customer持久化对象。因此在内存中共有两个Customer持久化对象,一个属于session1的缓存,一个属于session2的缓存。引用变量ab都引用session1缓存中的Customer持久化对象,而引用变量c引用session2缓存中的Customer持久化对象:

    Session session1=sessionFactory.openSession();
    Session session2=sessionFactory.openSession();
    Transaction tx1 = session1.beginTransaction();
    Transaction tx2 = session2.beginTransaction();

    Customer a=(Customer)session1.load(Customer.class,new Long(1));
    Customer b=(Customer)session1.load(Customer.class,new Long(1));
    Customer c=(Customer)session2.load(Customer.class,new Long(1));

    System.out.println(a= =b); //true
    System.out.println(a= =c); //false

    tx1.commit();
    tx2.commit();
    session1.close();
    session2.close();

    Java
    对象的持久化状态是相对于某个具体的Session实例的,以下代码试图使一个Java对象同时被两个Session实例关联:

    Session session1=sessionFactory.openSession();
    Session session2=sessionFactory.openSession();
    Transaction tx1 = session1.beginTransaction();
    Transaction tx2 = session2.beginTransaction();

    Customer c=(Customer)session1.load(Customer.class,new Long(1)); //Customer对象被session1关联
    session2.update(c); //Customer对象被session2关联
    c.setName("Jack"); //修改Customer对象的属性

    tx1.commit(); //执行update语句
    tx2.commit(); //执行update语句
    session1.close();
    session2.close();

    当执行session1load()方法时,OID1Customer对象被加入到session1的缓存中,因此它是session1的持久化对象,此时它还没有被session2关联,因此相对于session2,它处于游离状态。当执行session2update()方法时,Customer对象被加入到session2的缓存中,因此也成为session2的持久化对象。接下来修改Customer对象的name属性,会导致两个Session实例在清理各自的缓存时,都执行相同的update语句:

    update CUSTOMERS set NAME='Jack' …… where ID=1;
    在实际应用程序中,应该避免一个Java对象同时被多个Session实例关联,因为这会导致重复执行SQL语句,并且极容易出现一些并发问题。

    离线对象(Detached Objects):Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,他们不再受Hibernate管理。


    游离对象的特征。游离对象具有以下特征:
    (1) 不再位于Session的缓存中,也可以说,游离对象不被Session关联。
    (2) 游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程序删除了这条记录)。

    游离对象与临时对象的相同之处在于,两者都不被Session关联,因此Hibernate不会保证它们的属性变化与数据库保持同步。游离对象与临时对象的区别在于:前者是由持久化对象转变过来的,因此可能在数据库中还存在对应的记录,而后者在数据库中没有对应的记录。

    Session的以下方法使持久化对象转变为游离对象:
    (1) 当调用Sessionclose()方法时,Session的缓存被清空,缓存中的所有持久化对象都变为游离对象。如果在应用程序中没有引用变量引用这些游离对象,它们就会结束生命周期。
    (2)Sessionevict()方法能够从缓存中删除一个持久化对象,使它变为游离状态。当Session的缓存中保存了大量的持久化对象,会消耗许多内存空间,为了提高性能,可以考虑调用evict()方法,从缓存中删除一些持久化对象。但是多数情况下不推荐使用evict()方法,而应该通过查询语言,或者显式的导航来控制对象图的深度。

    Java对象在JVM中的生命周期:

    创建一个Java对象时,JVM会为这个对象分配一个内存空间,只要这个对象被引用变量引用,就一直存在于内存中,如果一个对象不被任何引用变量引用,就结束生命周期。Java集合(ListMapSet)存放的是Java对象的引用,当向集合中添加一个对象时,其实是把这个对象的引用添加到集合中。因此集合中含有的对象生命周期一直存在。

     

    操纵持久化对象

    1.   理解Session的缓存:

    Java里面,缓存通常是指Java对象的属性占用的内存空间,通常是一些集合类型的属性。在session接口的实现类SessionImpl中定义了一系列的Java集合,这些Java集合就构成了Session的缓存。

    Sessionsave()方法持久化一个对象时,这个对象被加入到Session的缓存中,以后即使应用程序中的引用变量不再引用这个对象,只要Session的缓存还没有被清空,这个对象仍然处于生命周期中。当Sessionload()方法加载一个对象时,Session会先判断缓存中是否已经存在这个对象了,如果存在,就不需要再到数据库中重新加载了。

    Session的缓存有两大作用:

    1.1.       减少访问数据库的频率。

    1.2.       保证缓存中的对象与数据库中的相关记录保持同步。

    Session有两个方法:一个commit()事务提交方法,还有flush()刷新缓存方法,都有着清理缓存的作用。flush()进行缓存的清理,执行一系列的SQL语句,但不会提交事务。而commit()方法会先调用flush()方法,然后在提交事务。

    2.   定义持久化类的建议:

    在应用程序中,用来实现业务问题实体的(如,在电子商务应用程序中的CustomerOrder)类就是持久化类。如果这些持久化类遵循一些简单的规则,Hibernate能够工作得更好,这些规则也被称作简单传统Java对象(POJO:Plain Old Java Object)编程模型。但是这些规则并不是必需的。最好要遵循以下几条主要的规则:

    1)     实现一个默认的(即无参数的)构造方法(constructor):

    我们强烈建议,在Hibernate中,为了运行期代理的生成,构造方法至少是(package)内可见的。

    2)     提供一个标识属性(identifier property):

    我们建议你对持久化类声明命名一致的标识属性。我们还建议你使用一个可以为空(也就是说,不是原始类型)的类型。

    3)     使用非final的类:

    代理(proxiesHibernate的一个重要的功能,它依赖的条件是,持久化类或者是非final的,或者是实现了一个所有方法都声明为public的接口。你也应该避免在非final类中声明public final的方法。

    4)     为持久化字段声明访问器(accessors)

    5)     如果你有如下需求,你必须重载 equals() hashCode()方法:

    想把持久类的实例放入Set中(当表示多值关联时,推荐这么做)

    想重用脱管实例

    Hibernate保证,仅在特定会话范围内,持久化标识(数据库的行)和Java标识是等价的。因此,一旦我们混合了从不同会话中获取的实例,如果希望Set有明确的语义,就必须实现equals()hashCode()

    3.   Session的保存、删除、更新和查询方法:

    3.1.   Sessionsave()方法:使用一个临时对象转变为持久对象。

    方法签名:public Serializable save(Object object) throws HibernateException;它完成以下操作:

    1)     把持久化类的实例加入到缓存中,使它变为持久化对象。

    2)     选用映射文件指定的标识符生成器为持久化对象分配唯一的OID

    3)     计划执行一个insert语句,把持久化对象当前的属性值组装到insert语句(SQL DML)中。值得注意的是,save()方法并不是立即执行SQL insert语句。只有当Session清理缓存时,才会执行SQL insert语句。

    另外,需要注意的是:Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系。所以当持久化的实例处于持久化状态时,不允许程序随意修改它的OID。其实,无论java对象处于瞬时状态、持久化状态还是脱管状态,程序都不应该修改它的OID3.2.   Session的update()方法:使一个脱管对象转变为持久化对象。

    方法签名:public void update(Object object) throws HibernateException;它完成以下操作:

    1)     把脱管对象重新加入到Session缓存中,使它变为持久化对象。

    2)     计划执行一个update语句。值得注意的是,Session只有在清理缓存的时候才会执行update语句,并且在执行时才会把持久化对象当前的属性值组装到update语句中。3.3.   Session的saveOrUpdate()方法:

           方法签名:public void saveOrUpdate(Object object) throws HibernateException ; saveOrUpdate()方法同时包含了save()update()方法的功能,如果传入的参数是瞬时对象,就调用save()方法;如果传入的参数是脱管对象,就调用update()方法;如果传入的参数是持久化对象,方法就直接返回。那么,saveOrUpdate()方法如果判断一个对象处于瞬时状态不是脱管状态呢?如果满足以下情况之一,Hibernate就把它作为临时对象:

    1)     Java对象的OID取值为null

    2)     Java对象具有version属性,并且取值了null

    3)     在映射文件中为<id>元素设置了unsaved-value属性,并且OID取值与unsaved-value属性值匹配。

    4)     在映射文件中为<version>元素设置了unsaved-value属性,并且version属性取值与unsaved-value属性值匹配。

    5)     自定义了HibernateInterceptor实现类,并且InterceptorisUnsaved()方法返回Boolean.TRUE

    3.4.   Session的delete()方法:

    方法签名:public void delete(Object object) throws HibernateException; delete()方法用于从数据库中删除与Java对象对应的记录。如果传入的参数是持久化对象,Session就计划执行一个delete语句。如果传入的参数是游离对象,先使游离对象被Session关联,使它变为持久化对象,然后计划执行一个delete语句。值得注意的也是,Session只有在清理缓存的时候才会执行delete语句。

    4.   通过主键ID取得数据对象:

    4.1.   Session的get()方法:

           方法签名:public Object get(Class clazz, Serializable id) throws HibernateException;根据给定的OID从数据库中加载一个持久化对象,若数据库中不存在与OID对应的记录,此方法返回null

           get()方法的执行顺序如下:

    1)     首先通过idsession缓存中查找对象,如果存在此id主键值的对象,直接将其返回。如果不存在,将进行第2步。

    2)     在二级缓存中查找,找到后将其返回。

    3)     如果在session缓存和二级缓存中都找不到此对象,刚从数据库加载拥有此id的对象。如果数据库也不存在这个拥有此id的对象,则返回null

    4.2.   Session的load()方法:

    方法签名:public Object load(Class theClass, Serializable id) throws HibernateException;根据给定的OID从数据库中加载一个持久化对象,若数据库中不存在与OID对应的记录,此方法将抛出org.hibernate.ObjectNotFoundException异常。

    对于getload的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null

    5.   Query接口:

    Hibernate提供Query接口,它用来执行HQL语句。

    5.1.   绑定参数

    5.1.1.      使用 “?”按参数位置绑定

    通过Query接口执行HQL语句时,可以先设定查询参数,然后通过setXXX()方法来绑定参数。如下

    Query query = session.createQuery("from User as u where u.age > ? and u.name like ?");

    query.setInteger(0, 25);

    query.setString(1, "%a%");

    List list = query.list();

    Hibernate提供了绑定各种类型的参数的方法,如参数为字符串类型,可调用setString(),如果参数为整数类型,可调用setInteger()方法,以此类推。这些setXXX()方法的第1个参数HQL查询语句中参数的位置,第2个参数代表HQL查询语句中参数的值。

    5.1.2.      使用 “:”后跟变量名来按命名参数绑定

    可以使用命名参数来取代使用“?”设置参数的方法,这可以不用依照特定的顺序来设定参数值,如上例可改成:

    Query query = session.createQuery("from User as u where u.age > :minAge and u.name like likeName");

    query.setInteger("minAge", 25);

    query.setString("likeName", "%a%");

    List list = query.list();

    使用命名参数方式的绑定方式有以下优势:

    1)     代码可读性更好。

    2)     命名参数不依赖它们在查询字符串中出现的位置。

    3)     在同一个查询中可以多次使用。

    所以,应该优先考虑使用命名参数方式。

    5.2.   使用命名查询(nameQuery):

    可以将HQL语句编写在程序之外,以避免硬编码在程序之中,这样要修改HQL语句时就很方便。在xxx.hbm.xml中使用<qiuery/>标签,并在<![CDATA[ ]]> 之间编写HQL,如下Student.hbm.xml

    ......

    <hibernate-mapping>

       <classname="org.qiujy.demo.User"table="user">

           <idname="id"column="id"type="java.lang.Integer">

               <generatorclass="native"/>

           </id>

           <propertyname="name"column="name"type="java.lang.String"/>

           <propertyname="age"column="age"type="java.lang.Integer"/>

       </class>

    <query name="queryUserByAgeAndName">

        <![CDATA[

        from User as u where u.age >:minAge and u.name like :likeName

    ]]>

    </query>

    </hibernate-mapping>

    在代码中这样来调用:

    Query query = session.getNamedQuery("queryUserByAgeAndName");

    query.setInteger("minAge", 25);

    query.setString("likeName", "%a%");

    List list = query.list();

    5.3.   Query接口的list()方法:

    Query接口的list()方法用于取得一个List类的实例,此实例中包括的可能是一个对象集合,也可能是一个对象数组集合。最常见的使用是用list()方法来取得一组符合实例对象。如上示例。

    5.4.   Query接口的uniqueResult()方法:

    当确信使用的HQL语句查询时返回的集合中只有一个对象时,就可以使用这个方法。但如果返回结果中有多个对象,使用这个方法会抛出org.hibernate.NonUniqueResultException异常,说“query did not return a unique result”。

    展开全文
  • Hibernate中的对象有3中状态,瞬时对象(TransientObjects)、持久化对象(PersistentObjects)和离线对象(DetachedObjects也叫做脱管对象),下面通过本文给大家分享Hibernate持久化对象的三个状态,一起看看吧
  • 持久化对象状态

    千次阅读 2016-12-03 21:19:25
    站在持久化的角度,Hibernate把对象分为了4种状态持久化状态,临时状态,游离状态和删除状态。Session的特定方法能使对象从一个状态转换到另一个状态。   临时对象(Transient): 在使用代理主键的情况下,OID ...

      站在持久化的角度,Hibernate把对象分为了4种状态:持久化状态,临时状态,游离状态和删除状态。Session的特定方法能使对象从一个状态转换到另一个状态。
      

    • 临时对象(Transient):
      在使用代理主键的情况下,OID 通常为 null;
      不处于Session的缓存中;
      在数据库中没有对应的记录。
      通常使用new创建一个新的对象,并且不设置它的id属性值,则这个对象就是临时对象。
    • 持久化对象 (也叫“托管”)(Persist):
      OID不为null;
      位于Session缓存中;
      若在数据库中已经有和其对应的记录,则持久化对象和数据库中的相关记录对应;
      Session在flush缓存时,会根据持久化对象的属性变化,来同步更新数据库;
      在同一个Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象。
    • 游离对象 (也叫”脱管”) (Detached):
      OID不为null;
      不再处于Session缓存中;
      一般情况需下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录。
    • 删除对象 (Removed):
      在数据库中没有和其OID对应的记录;
      不再处于Session 缓存中;
      一般情况下,应用程序不该再使用被删除的对象。

        这几种状态的对象转换图如下:
        
      image_1b327ru1f18eg1169tqfi771p429.png-81.6kB
       
      下面介绍Session能够转换对象状态的方法:

    • save()
      Session 的 save() 方法使一个临时对象转变为持久化对象;
      Session 的 save() 方法完成以下操作:
      1. 把 News 对象加入到 Session 缓存中,使它进入持久化状态;
      2. 选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID。
      (在使用代理主键的情况下, setId() 方法为 News 对象设置 OID 是无效的)
      3. 计划执行一条 insert 语句:在 flush 缓存的时候,hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系,当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID
       
      persist() 和 save() 区别:
      当对一个OID不为Null的对象执行save()方法时,会把该对象以一个新的OID保存到数据库中; 但执行persist()方法时会抛出一个异常。

    • get() 和 load()
      1. 这两个方法都可以根据给定的 OID 从数据库中加载一个持久化对象;
      2. 执行 get 方法: 会立即加载对象;(立即检索)
      执行 load 方法:若不使用该对象,则不会立即执行查询操作,而返回一个代理对象,直到使用到该对象的时候才会加载。(延迟检索)
      3. 如果在需要初始化代理对象之前已经关闭了session,load方法可能会抛出 LazyInitializationException 异常(懒加载异常)。例如:下面这段代码会抛出懒加载异常:

    public void testLoad(){
    
            News news = (News) session.load(News.class, 1);
    
            session.close();
            System.out.println(news); 
        }

    image_1b329j3m7evin1so5j1nln7dam.png-24.2kB
    而下面这段代码则可以正常加载:

    public void testLoad(){
    
            News news = (News) session.load(News.class, 1);
    
            System.out.println(news);
            session.close();
            System.out.println(news); 
        }

    image_1b329lqrt12o41tdi1ap71fm71m8613.png-10kB

    4. 若数据表中不存在与OID对应的记录,且Session也没有被关闭:
     get方法会返回null;
     load方法若不使用该对象的任何属性,则不会出现问题;否则将抛出ObjectNotFoundException异常。

    • update()
      1. Session 的update()方法可以使一个游离对象转变为持久化对象,并且计划执行一条 update 语句。
      2. 若希望Session仅在对象的属性发生变化时, 才执行 update() 语句,可以把映射文件中 <class> 元素的 select-before-update 设为 true,该属性的默认值为 false。(若该对象是持久化对象,且其属性并未发生改变,则就算不配置select-before-update为true,也不会进行update操作)
      3. 若更新一个持久化对象,通常不需要显示的调用update方法,因为在调用Transaction的commit()方法时,会先执行session的flush方法。
      4. 当update()方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同OID的持久化对象,会抛出异常,因为在Session 缓存中不能有两个OID相同的对象。
      5. 当update()方法关联一个游离对象时,如果在数据库中不存在相应的记录, 也会抛出异常。

    • saveOrUpdate()
      首先判断保存的对象是临时对象还是游离对象,若为临时对象,则调用save()方法,若是游离对象,则调用update()方法。
      判定对象为临时对象的标准:
      标准一: Java 对象的 OID 是否为 null,为null是临时对象,否则是游离对象。
      标准二: 如果在映射文件中为 <id> 设置了unsaved-value属性, 则OID取值等于这个unsaved-value属性值的Java对象为临时对象,否则为游离对象。
       
        saveOrUpdate执行流程如下:
       
      image_1b32btj7e16cs1un51n8li3p1f9v1g.png-19.5kB

    • delete()
      1. Session 的delete()方法既可以删除一个游离对象,也可以删除一个持久化对象。只要 OID 和数据表中一条记录对应,就会准备执行 delete 操作,若 OID 在数据表中没有对应的记录,则抛出异常。
      2. Session 的 delete() 方法处理过程为:计划执行一条delete 语句,把对象从 Session 缓存中删除,然后该对象进入删除状态。
      3. 默认情况下,在执行delete方法后,对象的id值仍然被保存在对象中,这在某些情形下(例如又对该对象执行saveOrUpdate()方法)会很不方便。Hibernate的配置文件hibernate.cfg.xml中有一个hibernate.use_identifier_rollback属性,其默认值为false,若把它设为true,则在执行delete()方法后,对象的id值将被置为null。

    展开全文
  • 对象持久化层的状态
  • Hibernate持久化对象的三个状态

    千次阅读 2015-08-15 16:42:52
    Hibernate中的对象有3中状态,瞬时对象(TransientObjects)、持久化对象(PersistentObjects)和离线对象(DetachedObjects也叫做脱管对象)。 下图3.1显示了瞬时对象持久化对象和离线对象之间的关系以及它们...

    在Hibernate中,对象有三种状态:临时状态(Transient)、持久状态(Persistent)和游离状态(Detached)。

    处于持久态的对象也称为PO(PersistenceObject),临时对象和游离对象也称为VO(ValueObject).
    1. 临时状态
    由new命令开辟内存空间的java对象,例如:

    User user=new User();

    时对象在内存孤立存在,它是携带信息的载体,不和数据库的数据有任何关联关系.

    (a)如果没有变量对该对象进行引用,它将被gc回收;

    (b)在Hibernate中,可通过session的save()或saveOrUpdate()方法将瞬时对象与数据库相关联,并将数据对应的插入数据库中,此时该临时对象转变成持久化对象.

    2. 持久状态
    处于该状态的对象在数据库中具有对应的记录,并拥有一个持久化标识.通过session的get()、load()等方法获得的对象都是持久对象。

    持久化对象被修改变更后,不会马上同步到数据库,直到数据库事务提交。在同步之前,持久化对象是脏的(Dirty)。

    (a)如果是用hibernate的delete()方法,对应的持久对象就变成临时对象,因数据库中的对应数据已被删除,该对象不再与数据库的记录关联.

    (b)当一个session执行close()或clear()、evict()之后,持久对象变成游离对象,此时该对象虽然具有数据库识别值,但它已不在HIbernate持久层的管理之下.

    持久对象具有如下特点:

    (1)和session实例关联;

    (2)在数据库中有与之关联的记录,并拥有持久化标识.

    3. 游离状态
    当与某持久对象关联的session被关闭后,该持久对象转变为游离对象.当游离对象被重新关联到session上时,又再次转变成持久对象(在Detached其间的改动将被持久化到数据库中)。
    游离对象拥有数据库的识别值,但已不在持久化管理范围之内。

    (a)通过update()、saveOrUpdate()等方法,游离对象可转变成持久对象.

    (b)如果是用hibernate的delete()方法,对应的游离对象就变成临时对象,因数据库中的对应数据已被删除,该对象不再与数据库的记录关联.

    (c)在没有任何变量引用它时,它将被gc在适当的时候回收;

    游离对象具有如下特点:

    (1)本质上与瞬时对象相同,在没有任何变量引用它时,JVM会在适当的时候将它回收;

    (2)比瞬时对象多了一个数据库记录标识值.

    示例:

    Session session=factory.openSession();
    User user=new User();
    //user对象处于临时状态。
    user.setName("张三");
    user.setAge(18);
    Transaction tran=Session.beginTransaction();
    session.save(user);
    //user对象转化为持久状态。
    tran.commit();
    session.close();
    //user对象转化为游离状态。
    user.setName("李四");
    Session session2=factory.openSession();
    Transaction tran2=Session2.beginTransaction();
    Session2.update(user);
    //user对象转化为持久状态。
    tran2.commit();(游离状态中对象的变动在再次持久时会被持久化到数据库) 
    Transaction tran3=Session.beginTransaction();
    Session2.delete(user);
    //user对象转化为临时状态。
    tran3.commit();
    session2.close();

    Session的不同操作对对象状态的影响:
    Session的save()方法
    save()方法将一个临时对象转变为持久对象。
    Session的update()方法
    update()方法将一个游离对象转变为持久对象。
    Session的lock()方法
    调用lock()方法将对象同Session相关联而不强制更新。
    Session的merge()方法
    拷贝指定对象的状态到具有相同对象标识符的持久对象。
    Session的saveOrUpdate()方法
    saveOrUpdate()方法对于临时对象,执行save()方法,对于游离对象,执行update()方法。

    Session的load()和get()方法
    load()方法和get()方法都可以根据对象的标识符加载对象,这两个方法加载的对象都位于Session的缓存中,属于持久对象。
    Session的delete()方法
    delete()方法用于从数据库中删除与持久化对象对应的记录。如果传入的是一个持久化对象,Session就执行一条delete语句。如果传入的参数是游离对象,先使分离对象与Session关联,使它变为持久化对象,然后才计划执行一个delete语句。
    Session的evict()方法
    evict()方法从Session的缓存中删除一个持久对象。

    展开全文
  • Hibernate持久化对象状态

    千次阅读 2016-02-22 08:57:22
    一、Hibernate持久化对象支持如下几种对象状态: 瞬态:对象由new操作符创建,且尚未与Hibernate Session关联的对象被认为出入瞬态。瞬态对象不会被持久化到数据库中,也不会被赋予持久化标识。如果程序中失去了瞬态...
  • 持久化对象三种状态的概述 Hibernate为了更好的来管理持久化类,特将持久化类分成了三种状态。在Hibernate中持久化对象可以划分为三种状态,分别为瞬时态,持久态和脱管态,一个持久化类的实例可能处于三种不同...
  • Hibernate中对象状态: 临时/瞬时状态持久化状态、游离状态。  临时状态 特点: 直接new出来的对象;  不处于session的管理; 数据库中没有对象的记录;  持久化状态 当调用session的save/saveOrUpdate/...
  • hibernate 持久化对象状态

    千次阅读 2014-05-30 23:13:53
    站在持久化的角度, Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态. Session 的特定方法能使对象从一个状态转换到另一个状态. 持久化对象状态 临时对象(Transient):  –在...
  • 我们已经知道,通过new新创建一个持久化实例时,该实例处于瞬态,为了让瞬态对象转换为持久化状态,Hibernate Session提供了两个方法: Serializable save(Object obj) 将obj对象转变为持久化状态,该对象的属性...
  • 持久化对象的三种状态简述 在Hibernate中持久化类的对象可以划分为三种状态,分别是: 瞬态,持久态,脱管态。 一、瞬时状态(Transient) 瞬时对象特点: (1) 不和 Session 实例关联 (2) 在数据库中没有和瞬时对象...
  • hibernate持久化对象状态 .

    千次阅读 2012-04-18 00:57:05
    持久化对象状态: 瞬时对象(Transient Objects):使用new操作符初始化的对象不是立刻就持久化的。他们的状态是瞬时的,也就是说他们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其他...
  • 为了让瞬态对象转换为持久化状态,HibernateSession提供了如下几个方法。 1) Serialzable save(Object obj):将obj对象变为持久化状态,该对象的属性将被保存到数据库。 2) void persist(Object obj):将obj对象...
  • 【Hibernate】持久化对象的三种状态

    热门讨论 2016-08-25 23:42:00
    【回顾】  上篇博客,进一步对Hibernate的基础语义做了简单的总结。... 本篇博客的内容是持久化对象中的三种状态,即:瞬时对象(Transient Objects)、持久化对象(Persist Objects)和离线对象(Deta
  • Hibernate 持久化对象状态

    千次阅读 2014-06-12 16:23:20
    持久化对象状态: 瞬时对象(Transient Objects):使用new操作符初始化的对象不是立刻就持久化的。他们的状态是瞬时的,也就是说他们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何...
  • Hibernate为了方便管理持久化类,将持久化类分成了三种状态. 瞬时态 transient :(临时态)特点:持久化对象没有唯一标识OID.没有纳入Session的管理 持久态 persistent :特点:持久化对象有唯一标识OID.已经纳入到...
  • 本篇博客将要介绍hibernate中持久化对象状态,并使用hibernate中的核心接口进行一些JDBC基本操作,来观察状态的转移。 准备工作很重要,需要了解一些专业词汇,所谓专业词汇,意思大家都懂,只是在专业领域里起个...
  • 游离对象 临时对象 持久化对象

    千次阅读 2018-04-25 18:49:52
    临时对象是指new出的对象,没有对ID赋值;游离状态时候指对临时状态赋值ID的状态持久化对象是指该对象已经插入数据库中;
  • -对象的临时状态持久化状态和游离状态 -用session的update方法使游离对象转化为持久化对象 session级别的缓存又叫一级缓存;SessionFactory级别的缓存叫做二级缓存。 在hibernate应用中java对象状态 -...
  • hibernate持久化对象的四个状态

    千次阅读 2017-09-21 22:12:35
    2、持久化状态(Persistent) 3、游离状态(Detached) 4、删除状态瞬时状态(Transient) 通过new开辟内存空间创建的实体对象,但是它没有纳入hibernate session的管理之中,如果没有变量对它引用,它将会被JVM...
  • 【hibernate进阶】hibernate持久化对象的三种状态

    千次阅读 热门讨论 2016-05-28 20:47:36
    Hibernate持久化对象的三种状态:瞬时对象(Transient Objects),持久化对象(Persist Objects),离线对象(Detached Objects)。 三种状态:  瞬时对象(Transient Objects):使用new 操作符初始化的对象不是...
  • 【SSH框架】--Hibernate持久化对象的三种状态

    千次阅读 热门讨论 2016-02-12 20:11:50
    持久化是将程序数据在持久状态和瞬时状态间转换的机制。持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在的数据库中,或者存储...
  • hibernate持久化对象的三种状态,瞬态,持久化,托管 ; 三种状态之间的的状态转换图 ; save(),persist()的区别与联系 ; load() 和 get()方法的区别与联系; update()和updateOrSave()方法的用法 ; 更新持久化...
  • JPA持久化上下文与对象状态

    千次阅读 2016-06-10 13:17:03
    hibernate 认为一个有id的新对象为detached. 自动脏检查可以通过继承org.hibernate.CustomEntityDirtinessStrategy并设置hibernate.entity_...对应某个id的实例在持久化上下文中只有一个对象. Hibernate,find时总是
  • 对于需要被持久化的Java对象,在它的生命周期中,可处于以下三个状态之一: (1) 临时状态(transient):刚刚用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象被称为临时对象。 (2
  • 持久化:将内存当中的一个对象持久化到数据库当中的过程。Hibernate框架就是用来进行持久化的框架。 持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate当中就可以称为持久化持久化类 = ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 202,861
精华内容 81,144
关键字:

对象状态的持久化是通过