`

写得很不错的-Hibernate中的实体状态(二)

阅读更多

(2)session.merge ()方法

该方法将修改表中记录,其所需要的实体状态为脱管状态,但是注意,它并不影响调用方法前后的状态,也即该实体依然是脱管状,见例6.4。

例6.4:session.merge ()方法对状态的变化

     public void run() {

          //创建UserInfo实例

          UserInfo userInfo = new UserInfo();

          //使之成为脱管状态

          userInfo.setId(11112);

          userInfo.setName("RW3");

          userInfo.setSex("M");

          //创建UserInfo实例

          UserInfo userInfo2 = new UserInfo();

          //使之成为脱管状态

          userInfo2.setId(11112);

          userInfo2.setName("RW4");

          userInfo2.setSex("F");

          //启动Session

          Session session = HibernateSessionFactory.currentSession();

          //启动事务

          Transaction tx = session.beginTransaction();

          //调用merge方法,此时UserInfo实体状态并没有被持久化

          session.merge(userInfo);

          //调用merge方法,此时UserInfo实体状态并没有被持久化

          //但是数据库中的记录被更新了

          ①session.merge(userInfo2);

          //merge方法与update方法的差别在于针对同样的操作update方法会报错

          //原因在于update方法使得实体状态成为了持久化状态,而Session中不允许两个持久化实体有同样的持久化标识

          ②//session.update(userInfo);

          //session.update(userInfo2);

         //以下两句不会发送SQL,因为userInfo2不是持久化状态的实体

         ③userInfo2.setName("RW5");

          userInfo2.setSex("M");

          //提交事务

          tx.commit();

          //关闭Hibernate Session

          HibernateSessionFactory.closeSession();

     }

针对该段代码将执行如下SQL语句:

Hibernate:

/* ①session.merge(userInfo2)的动作 */

select

        userinfo0_.id as id0_0_,

        userinfo0_.NAME as NAME0_0_,

        userinfo0_.SEX as SEX0_0_,

        userinfo0_.roomid as roomid0_0_

    from

        userinfo userinfo0_

    where

        userinfo0_.id=?

Hibernate:

/* ①session.merge(userInfo2)的动作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

session.merge()方法会首先发送一句select语句,去数据库端获取UserInfo持久化标识所对应的表记录;然后自动生成一个持久化状态的UserInfo实体,与脱管状态的UserInfo实体做比较是否有所改变;一旦发生了改变,才会发送update语句执行更新。而按执行顺序,若两句session.merge()方法针对同一个脱管状态的UserInfo实体,那其结果只会执行最后一个session.merge()方法所发出的update语句。即使执行了session.merge()方法,UserInfo实体依然是脱管状态,因此③userInfo2. setName("RW5")的语句不会同步数据库中的表。

(3)session.lock()方法

他为了解决事务处理而使用,它会将实体从脱管状态转变为持久化状态。但是值得注意的是,调用session.lock()方法后,脱管状态的实体信息不会同步到数据库,而是会从数据库中返回该持久化状态。即使在脱管状态对实体属性进行了修改,一旦调用了session.lock()方法,这种修改就成了无效,见例6.5。

例6.5:session.lock()方法对状态的变化

     public void run() {

          //创建UserInfo实例

          UserInfo userInfo = new UserInfo();

          //使之成为脱管状态

          userInfo.setId(11112);

          userInfo.setName("RW3");

          userInfo.setSex("M");

          //启动Session

          Session session = HibernateSessionFactory.currentSession();

          //启动事务

          Transaction tx = session.beginTransaction();

         //发送select获取数据库中的当前记录(执行的SQL根据LockMode不同有不同的方式)

         //UserInfo实体将从脱管状态转变为持久化状态

          ①session.lock(userInfo,LockMode.UPGRADE_NOWAIT);

          //对当前UserInfo实体进行更新将同步数据库中的记录

          ②userInfo.setName("RW8");

          //提交事务

          tx.commit();

          //关闭Hibernate Session

          HibernateSessionFactory.closeSession();

     }

针对该段代码将执行如下SQL语句:

Hibernate:

/* ①session.lock(userInfo,LockMode.UPGRADE_NOWAIT)的动作 */

select

        id

    from

        userinfo

    where

        id =? for update

            nowait

Hibernate:

/*②userInfo.setName("RW8")的动作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

session.lock()方法并不是为了将脱管状态的对象转变为持久化状态,而是为了事务处理。

(4)session.saveOrUpdate()方法

它是Hibernate提供的既可以新增也可以更新的方法,该方法使实体状态从脱管或瞬时直接变成持久化。session.saveOrUpdate()方法对实体的持久化标识非常敏感。当实体持久化标识存在,就会发送update SQL,当持久化标识不存在,就会发送insert SQL,见例6.6。

例6.6:session.saveOrUpdate()方法对状态的变化

     public void run() {

          //创建UserInfo实例

          UserInfo userInfo = new UserInfo();

          //使之成为脱管状态

          userInfo.setId(11112);

          userInfo.setName("RW3");

          userInfo.setSex("M");

          //创建UserInfo实例,其为瞬时状态

          UserInfo userInfo2 = new UserInfo();

          userInfo2.setName("RW3");

          userInfo2.setSex("M");

          //启动Session

          Session session = HibernateSessionFactory.currentSession();

          //启动事务

          Transaction tx = session.beginTransaction();

          //UserInfo存在持久化标识,因此为新增,从瞬时状态成为持久化状态

          ①session.saveOrUpdate(userInfo2);

          //同步数据库表记录

          ②userInfo2.setName("RW9");

          //UserInfo存在持久化标识,因此为修改,从脱管状态成为持久化状态

          ③session.saveOrUpdate(userInfo);

          //同步数据库表记录

          ④userInfo.setName("RW10");

          //提交事务

          tx.commit();

          //关闭Hibernate Session

          HibernateSessionFactory.closeSession();

     }

针对该段代码将执行如下SQL语句:

Hibernate:

/* ①session.saveOrUpdate(userInfo2)的动作 */

insert

        into

            userinfo

            (NAME, SEX, roomid, id)

        values

            (?, ?, ?, ?)

Hibernate:

/* ②session.saveOrUpdate(userInfo)的动作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

Hibernate:

/* ③session.saveOrUpdate(userInfo)的动作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

根据代码的执行,对同一持久化UserInfo属性需要改变多次,那只会以最后的属性为准,因此③session.saveOrUpdate(userInfo)和④userInfo.setName("RW10")虽然从理论上需要发送两句update SQL到数据库,但其实只会产生一句。

(5)session.createQuery()方法

它为HQL语句调用,HQL(HibernateQusery Language)是Hibernate框架自定义的一种面向对象的语言,类似SQL语言,用以与数据库进行交互。Hibernate将HQL解析成SQL语句与数据库交互。HQL被执行后,其所关系到的实体对象将从瞬时状态转变为脱管状态,见例6.7。

例6.7:session.createQuery()方法对状态的变化

//一个内部类,作为SQL查询的参数传递

     class RoomDTO {

          Long id;

          public Long getId() {

               return id;

          }

          public void setId(Long id) {

               this.id = id;

          }

     }

    

     public void run() {

          // 创建一个JavaBean作为参数传递

          RoomDTO roomDTO = new RoomDTO();

          //设置id属性的值

          roomDTO.setId(1L);

          // 启动Session

          Session session = HibernateSessionFactory.currentSession();

          // 启动事务

          Transaction tx = session.beginTransaction();

          //session.createQuery方法作为HQL查询的执行

          //其中setProperties方法作为":id"的参数传递,要求roomDTO实例中必须包含id

          //属性和getId、setId方法

          //由于SQL中包含有3个实体:room、room.id、userinfo,因此返回的结果将是对象数组

          ①Iterator i = session

                    .createQuery(

                              "select room, room.id, userinfo from Room room, UserInfo userinfo where room.id = userinfo.room.id and room.id = :id")

                    .setProperties(roomDTO).iterate();

          //通过迭代将3个实体对象转型,得到最终结果

          //其中Room实体和UserInfo实体对应的实体状态为脱管,roomid则为一个Long类型

          while (i.hasNext()) {

               //获取对象数组转型

               Object[] object = (Object[]) i.next();

               //获取脱管状态的Room实体

               ②Room roomr = (Room) object[0];

               System.out.println(roomr.getName());

               System.out.println(roomr.getRoomnumber());

               //获取roomid

               ③Long roomid = (Long) object[1];

               System.out.println(roomid);

               //获取脱管状态的UserInfo实体

               ④UserInfo userinfor = (UserInfo) object[2];

               System.out.println(userinfor.getName());

               System.out.println(userinfor.getSex());

          }

          // 提交事务

          tx.commit();

          // 关闭Hibernate Session

          HibernateSessionFactory.closeSession();

     }

针对该段代码将执行如下SQL语句:

Hibernate:

/* 执行

①select

        room,

        room.id,

        userinfo

    from

        Room room,

        UserInfo userinfo

    where

        room.id = userinfo.room.id

        and room.id = :id

的HQL语句 */

select

            room0_.id as col_0_0_,

            room0_.id as col_1_0_,

            userinfo1_.id as col_2_0_

        from

            room room0_,

            userinfo userinfo1_

        where

            room0_.id=userinfo1_.roomid

            and room0_.id=?

Hibernate:

/* ②Room roomr = (Room) object[0]的动作(数据库中有一条记录,取第一条) */

select

        room0_.id as id1_0_,

        room0_.NAME as NAME1_0_,

        room0_.roomnumber as roomnumber1_0_

    from

        room room0_

    where

        room0_.id=?

Hibernate:

/* ④UserInfo userinfor = (UserInfo) object[2]的动作(数据库中有两条记录,取第一条) */

select

        userinfo0_.id as id0_0_,

        userinfo0_.NAME as NAME0_0_,

        userinfo0_.SEX as SEX0_0_,

        userinfo0_.roomid as roomid0_0_

    from

        userinfo userinfo0_

    where

        userinfo0_.id=?

Hibernate:

/* ④UserInfo userinfor=(UserInfo)object[2]的动作(数据库中有两条记录,取第二条)*/

select

        userinfo0_.id as id0_0_,

        userinfo0_.NAME as NAME0_0_,

        userinfo0_.SEX as SEX0_0_,

        userinfo0_.roomid as roomid0_0_

    from

        userinfo userinfo0_

    where

        userinfo0_.id=?

可以看到,Hibernate在执行这段代码的HQL时,并不会一次性把所有的room表和userinfo表的字段都捞取出来,而是先获取其主键。在之后真正要使用这两个表所对应的实体对象(Room和UserInfo)时,才会调用select语句去获取其所有字段,这是“延时求值”的机制在起作用。session.createQuery()方法不会使实体成为持久化状态,因此对Room和UserInfo的实体属性进行改变不会同步数据库。

调用createQuery()方法执行HQL时,有多种方式可以传递参数,本例提供了一种常见的方式——setProperties()。


说明 除了createQuery()方法外,Hibernate还提供了外置命名查询(getNameQuery()方法)、结果集过滤(createFilter()方法)、条件查询(createCriteria()方法)、原生SQL查询(createSQLQuery()方法)来实现抓取数据。

6.1.6 结语
在本小节中,将对Hibernate中的持久化方法做一个总结,也作为本问题的结语。

(1)瞬时—脱管状态的方法有以下几种。

· 直接将实体的持久化标识进行改变。

· 调用session.createQuery()方法。

· 调用session.getNameQuery()方法。

· 调用session.createFilter()方法。

· 调用session.createCriteria()方法。

· 调用session.createSQLQuery()方法。

(2)瞬时—持久化状态的方法有以下几种。

· 调用session.save()方法。

· 调用session.saveOrUpdate()方法。

(3)脱管—持久化状态的方法有以下几种。

· 调用session.load()方法。

· 调用session.lock()方法。

· 调用session.update()方法。

· 调用session.saveOrUpdate()方法。

(4)脱管—瞬时状态的方法有以下几种。

· 直接将实体的持久化标识清除。

· 调用session.delete()方法。

(5)持久化—脱管状态的方法:关闭Hibernate Session。

(6)持久化—瞬时状态的方法。调用session.delete()方法。

(7)脱管状态-脱管状态但影响数据库记录的方法:调用session.merger()方法。

分享到:
评论

相关推荐

    Hibernate中的实体状态及转换

    Hibernate 实体状态 瞬态(transient) 持久化(persistent) 脱管(detached) 转换

    Hibernate+中文文档

    10.1. Hibernate对象状态(object states) 10.2. 使对象持久化 10.3. 装载对象 10.4. 查询 10.4.1. 执行查询 10.4.2. 过滤集合 10.4.3. 条件查询(Criteria queries) 10.4.4. 使用原生SQL的查询 10.5. 修改...

    hibernate3.2中文文档(chm格式)

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    Hibernate学习笔记和资料

    hibernate概述,hibernate入门Demo,hibernate配置文件详解(全局配置,实体类映射配置),配置实体规则,核心API详解(Configuration,sessionFactory,session,Transaction),hibernate中的对象状态以及刷新能缓存机制 ...

    JPA学习笔记-EJB-05JPA实体对象状态和实体对象的高级操作

    虽然持久化实体的状态在ORM中是一个老生常谈的问题,但是说实在的,我们在开发过程中真的不太在意实体的状态。在Web一般情况下也都是交给Spring去管理实体管理器(EntityManager),所以我们还是有必要啰嗦一下,...

    Hibernate中文详细学习文档

    10.1. Hibernate对象状态(object states) 10.2. 使对象持久化 10.3. 装载对象 10.4. 查询 10.4.1. 执行查询 10.4.2. 过滤集合 10.4.3. 条件查询(Criteria queries) 10.4.4. 使用原生SQL的查询 10.5. 修改...

    HibernateAPI中文版.chm

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    Hibernate 中文 html 帮助文档

    10.1. Hibernate对象状态(object states) 10.2. 使对象持久化 10.3. 装载对象 10.4. 查询 10.4.1. 执行查询 10.4.1.1. 迭代式获取结果(Iterating results) 10.4.1.2. 返回元组(tuples)的查询 10.4.1.3. 标量(Scalar)...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的特征  8.3.3 被删除对象的特征  8.3.4 游离对象的特征  8.4 Session接口的详细用法  8.4.1 Session的save()和persist()...

    05_传智播客hibernate教程_实体对象的三种状态与saveOrUpdate方法

    05_传智播客hibernate教程_实体对象的三种状态与saveOrUpdate方法

    HiberNate实体

    hibernate实体有三个状态 1、瞬时状态 对象由new操作符创建,尚未与Session关联的对象被认为处于瞬态.瞬态对象不会持久化到数据库中,也不会被赋予持久化标识.而这个时候只在内存中存在,与数据库无关 2、持久状态 ...

    Hibernate实战(第2版 中文高清版)

    第一部分 从Hibernate和EJB 3.0开始  第1章 理解对象/关系持久化   1.1 什么是持久化   1.1.1 关系数据库   1.1.2 理解SQL   1.1.3 在Java中使用SQL   1.1.4 面向对象应用程序中的持久化   1.2 范式不...

    jpa-hibernate-alura:Alura的Java和JPA课程

    Alura-Java和JPA课程:使用JPA2和Hibernate持久化对象 这是我在课程之后开发的代码。 我已经对原始版本进行了一些更改。 内容 JPA和Hibernate简介 使用数据库 面向对象范式 在Java代码中避免使用SQL JDBC和SQL维护...

    hibernate-search:Hibernate搜索:全文搜索域模型

    通过Hibernate ORM会话修改的实体进行,以始终使索引保持最新状态。 ,可轻松构建全文本搜索查询并以Hibernate ORM实体的形式检索匹配。 以及更多: Search DSL中的许多不同和, 。 搜索查询返回的是而不是实体,...

    传智播客李勇hibernate源码1-20课

    05_实体对象的三种状态与saveOrUpdate方法 06_完善HibernateUtil类及hql查询入门 07_实体类或属性名与数据库关键字冲突问题 10_使用Hibernate完成CRUD实验的步骤说明 11_完成CRUD实验并回顾和补充细节知识(上)...

    精通hibernate:对象持久化技术孙卫琴第二版part2

    本章站在持久化层的角度,Java对象在生命周期中可处于临时状态、持久化状态、删除状态和游离状态。处于持久化状态的Java对象位于一个Session实例的缓存中,Session能根据这个对象的属性变化来同步更新数据库。 8.1 ...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    最全Hibernate 参考文档

    1. 在Tomcat中快速上手 1.1. 开始Hibernate之旅 1.2. 第一个持久化类 1.3. 映射cat 1.4. 与Cat同乐 1.5. 结语 2. 架构(Architecture) 2.1. 概况(Overview) 2.2. 实例状态 2.3. JMX整合 2.4. 对JCA的支持 3. 配置 ...

    Hibernate注释大全收藏

    上述实体映射到数据库中的时候对应 Order 实体Bean, 其具有 id, lastUpdate, lastUpdater 三个属性。如果没有@MappedSuperclass 注解,则父类中属性忽略,这是 Order 实体 Bean 只有 id 一个属性。 映射实体Bean的...

    hibernate 体系结构与配置 参考文档(html)

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

Global site tag (gtag.js) - Google Analytics