• hibernate中session的三种状态


    Hibernate中的对象有三种状态: 瞬时状态 (Transient),持久状态 (Persistent),

    1. 脱管状态 (Detached)

    1. 1. 瞬时状态 (Transient)

    由 new 命令开辟内存空间的 Java 对象,也就是平时所熟悉的普通 Java 对象。

    如: Student stu = new Student();

    瞬时对象特点:

    (1) 不和 Session 实例关联

    (2) 在数据库中没有和瞬时对象关联的记录

    2. 2. 持久状态 (Persistent)

    持久的实例在数据库中有对应的记录,并拥有一个持久化标识 (identifier).

    持久对象总是与 Session 和 Transaction 相关联,在一个 Session 中,对持久对象的改变不会马上对数据库进行变更,而必须在Transaction 终止,也就是执行 commit() 之后,才在数据库中真正运行 SQL 进行变更,持久对象的状态才会与数据库进行同步。在同步之前的持久对象称为脏 (dirty) 对象。

    瞬时对象转为持久对象:

    (1) 通过 Session 的 save() 和 saveOrUpdate() 方法把一个瞬时对象与数据库相关联,这个瞬时对象就成为持久化对象。

    (2) 使用 fine(),get(),load() 和 iterater() 待方法查询到的数据对象,将成为持久化对象。

    持久化对象的特点:

    (1) 和 Session 实例关联

    (2) 在数据库中有和持久对象关联的记录

    3. 3. 脱管状态 (Detached)

    与持久对象关联的 Session 被关闭后,对象就变为脱管对象。对脱管对象的引用依然有效,对象可继续被修改。

    脱管对象特点:

    (1) 本质上和瞬时对象相同

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

    持久对象转为脱管对象:

    当执行 close() 或 clear(),evict() 之后,持久对象会变为脱管对象。

    瞬时对象转为持久对象:

    通过 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把脱管对象变为持久对象。

    三种状态相互转化的状态图如下:

    Hibernate三种状态

    4 .结合 save(),update(),saveOrUpdate() 方法说明对象的状态

    (1)Save() 方法将瞬时对象保存到数据库,对象的临时状态将变为持久化状态。当对象在持久化状态时,它一直位于 Session 的缓存中,对它的任何操作在事务提交时都将同步到数据库,因此,对一个已经持久的对象调用 save() 或 update() 方法是没有意义的。如:

    Student stu = new Strudnet();

    stu.setCarId(“200234567”);

    stu.setId(“100”);

    // 打开 Session, 开启事务

    session.save(stu);

    stu.setCardId(“20076548”);

    session.save(stu); // 无效

    session.update(stu); // 无效

    // 提交事务,关闭 Session

    (2)update() 方法两种用途重新关联脱管对象为持久化状态对象,显示调用 update() 以更新对象。调用 update() 只为了关联一个脱管对象到持久状态,当对象已经是持久状态时,调用 update() 就没有多大意义了。如:

    // 打开 session ,开启事务

    stu = (Student)session.get(Student.class,”123456”);

    stu.setName(“Body”);

    session.update(stu); // 由于 stu 是持久对象,必然位于 Session 缓冲中,

    对 stu 所做的变更将 // 被同步到数据库中。所以 update() 是没有意义的,可以不要这句效果一样的。

    // 提交事务,关闭 Session

    Hibernate 总是执行 update 语句,不管这个脱管对象在离开 Session 之后有没有更改过,在清理缓存时 Hibernate 总是发送一条update 语句,以确保脱管对象和数据库记录的数据一致,如:

    Student stu = new Strudnet();

    stu.setCarId(“1234”);

    // 打开 Session1, 开启事务

    session1.save(stu);

    // 提交事务,关闭 Session1

    stu.set(“4567”); // 对脱管对象进行更改

    // 打开 Session2, 开启事务

    session2.update(stu);

    // 提交事务,关闭 Session2

    注:即使把 session2.update(stu); 这句去掉,提交事务时仍然会执行一条 update() 语句。

    如果希望只有脱管对象改变了, Hibernate 才生成 update 语句,可以把映射文件中 <class> 标签的 select-before-update 设为true, 这种会先发送一条 select 语句取得数据库中的值,判断值是否相同,如果相同就不执行 update 语句。不过这种做法有一定的缺点,每次 update 语句之前总是要发送一条多余的 select 语句,影响性能。对于偶尔更改的类,设置才是有效的,对于经常要更改的类这样做是影响效率的。

    (3)saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,对于传入的对象, saveOrUpdate() 首先判断其是脱管对象还是临时对象,然后调用合适的方法。

    注:并非到事务提交才对数据库操作,提交只是把变更持久化,实际上通过flush是可以操作的,只是这个变更只能在本事务看到而已。

  • 相关阅读:
    IOS Charles(代理服务器软件,可以用来拦截网络请求)
    Javascript中addEventListener和attachEvent的区别
    MVC中实现Area几种方法
    Entity Framework Code First 中使用 Fluent API 笔记。
    自定义JsonResult解决 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    An entity object cannot be referenced by multiple instances of IEntityChangeTracker 的解决方案
    Code First :使用Entity. Framework编程(8) ----转发 收藏
    Code First :使用Entity. Framework编程(6) ----转发 收藏
    Code First :使用Entity. Framework编程(5) ----转发 收藏
  • 原文地址:https://www.cnblogs.com/youk/p/2262596.html
Copyright © 2020-2023  润新知