hibernate5(8)操纵对象入门[3]操控对象封装方法

为什么要说是“封装方法”呢?因为它帮我们封装好了底层的增删改查操作,直接调用相应方法即可灵活地操作我们数据库数据。它们由Session接口提供,下面我们通过实例一一分析这些方法。

1.save方法

Session 的 save() 方法使一个临时对象转变为持久化对象

Session 的 save() 方法完成以下操作:

1. 把 News 对象加入到 Session 缓存中,使它进入持久化状态

2. 选用映射文件指定的标识符生成器,为持久化对象分配唯一的 OID。在 使用代理主键的情况下,setId() 方法为 News 对象设置 OID 是无效的。

3. 计划在 flush 缓存的时候,执行一条 insert 语句。

注意:

1. Hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系。当 News 对象处于持久化状态时,不允许程序随意修改它的 ID,否则会报异常:org.hibernate.HibernateException: identifier of an instance of com.zeng2.model.User was altered from 17(持久化状态的原有值) to 100(新修改的值)

所以在实际开发中,我们应该将setId()设为private防止用户更改实体id

2. 在一般完成持久化对象的初始化工作时,我们应先完成资源准备(设定成员属性值)后,再调用save方法。否则会增加额外的sql语句,如下所示:

//先设值再保存
User user1 = new User();
user1.setName("name1");
session.save(user1);
//Hibernate: insert into t_user2 (name, id) values (?, ?)
//先保存再设值
User user2 = new User();
session.save(user2);
user2.setName("name2");
//Hibernate: insert into t_user2 (name, id) values (?, ?)
//Hibernate: update t_user2 set name=? where id=? update t_user2 set name=? where id=?

2. persist方法

persist和save都能用来持久化对象,但它和user的区别是:当对一个 OID 不为 Null 的对象执行 save() 方法时,会把该对象以一个新的 oid 保存到数据库中;但执行 persist() 方法时会抛出一个异常。

//测试persist和save的区别
User user = new User();
user.setId(100);
session.save(user);
//执行Hibernate: insert into t_user2 (name, id) values (?, ?)
User user2 = new User();
user2.setId(200);
session.persist(user2);
//报异常org.hibernate.PersistentObjectException: detached entity passed to persist: com.zeng2.model.User

3. get和load方法

  1. 相同点:

    都可以根据跟定的 OID 从数据库中加载一个持久化对象

  2. 区别:
    1. 当数据库中不存在与 OID 对应的记录时,load() 方法抛出 ObjectNotFoundException 异常,而 get() 方法返回 null。
    2. 两者采用不同的延迟检索策略:load默认使用懒加载策略,除非将相应对象的获取策略设为即时加载。而get只要调用了,都会立即从数据库中甲在数据。

4. update方法

使一个游离对象转变为持久化对象,并且计划在flush时执行一条 update 语句

在一下情况使用会抛出异常:

1. 当 update() 方法关联一个游离对象时,如果在 Session 的缓存中已经存在相同 OID 的持久化对象,会抛出异常

2. 当 update() 方法关联一个游离对象时,如果在数据库中不存在相应的记录,也会抛出异常.

下面是我们的测试代码:

//测试update
User user = new User();
session.update(user);
//报异常:org.hibernate.TransientObjectException: The given object has a null identifier: com.zeng2.model.User
User user = new User();
user.setId(1);//数据库中存在的id
session.update(user);
//Hibernate: update t_user2 set name=? where id=?
User user = new User();
user.setId(111111);//数据库中不存在的id
session.update(user);
//报异常:org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
User user = session.get(User.class, 1);
User user2 = new User();
user2.setId(1);
session.update(user2);//更新一个在session缓存中已存在的对象
//报异常:org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.zeng2.model.User#1]

5. saveOrUpdate方法

Session 的 saveOrUpdate()可以看成是save和update的整合,两者形成有效互补。

它的执行过程吐下图所示:

Created with Rapha?l 2.1.0saveOrUpdate对象游离对象(yes),临时对象(no)更新对象保存对象yesno

我们常常根据id是否为null来判定来判断一个对象的状态,下面来看一个测试实例:

//测试saveOrUpdate
//1. 临时对象
User user = new User();
session.saveOrUpdate(user);
//Hibernate: insert into t_user2 (name, id) values (?, ?)
//2. 设置id构造伪游离对象
User user = new User();
user.setId(1);//数据库存在此id对应记录
session.saveOrUpdate(user);
//Hibernate: update t_user2 set name=? where id=?
//3. 构造id,但不存在于数据库,会报异常
User user = new User();
user.setId(111111);//数据库不存在此id对应记录
session.saveOrUpdate(user);
//org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

6. merge方法

把一个游离对象的属性复制到一个持久化对象中.先看我们的测试代码:

//报异常:org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
//      User user = session.get(User.class, 1);
//      User user2 = new User();
//      user2.setId(1);
//      session.update(user2);
        //报异常:org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.zeng2.model.User#1]

        //测试merge
        User user = session.get(User.class, 1);
        System.out.println(user3.getName());//name
        User user2 = new User();
        user2.setId(1);
        user2.setName("newName");
        session.merge(user2);
        System.out.println(user3.getName());//newName
        System.out.println(user == user2);//false
        System.out.println(user2 == user3);//false
        System.out.println(user3 == user);//true
        //Hibernate: update t_user2 set name=? where id=?
        /*查看数据库,记录成功更新:
        +----+---------+
        | id | name    |
        +----+---------+
        |  1 | newName |
        */

从上面我们可以看出,当session存在特定id的对象时,我们尝试自己伪造一个相同id对象并通过update来对其持久化时,会出现错误.而我们使用merge时却能成功更新,下面我们结合这个例子来分析调用merge方法的运行流程:

1. 如果user2是一个游离对象(id不为null)

1. 先到session缓存中查找id和user2相同的User,如果找到了(找到user),并将user2的值复制给user,在flush时执行update语句,从这里看,这就是我们操作更新的原因.还没完,它还会返回user的一个引用(这时候,user的值是user2复制完成后的值)所以打印时user3.getName=newName,并且user3 == user

2. 如果没在session缓存中找到,会查询数据库有没相同的记录:

1. 如果存在,则获取下来(设为oUser,此时未持久化对象),并将user2的属性复制到oUser中,同时返回oUser的引用到user3,并计划在flush时执行一条update语句更新数据库

2. 如果不存在,则会新建一个对象(设为nUser),将user2的属性复制到这个nUser中,再调用save方法持久化nUser,并返回nUser的引用,此时nUser == user3 为true

2. 如果user2是一个临时对象(id为null)

1. 新建一个对象(设为nUser),将user2的属性复制到这个nUser中,再调用save方法持久化nUser,并返回nUser的引用,此时nUser == user3 为true

根据这个流程分析,在整个过程中,我们的user2始终是非持久性对象.不像使用update,方法调用成功后,入参必定为持久化对象.

下面是一张流程执行狂徒,能够加深我们的理解:

7. delete方法

Session 的 delete() 方法既可以删除一个游离对象,也可以删除一个持久化对象

Session 的 delete() 方法处理过程:

1. 计划执行一条 delete 语句(在flush时正式执行),把对象从 Session 缓存中删除,该对象进入删除状态。

2. Hibernate 的 cfg.xml 配置文件中有一个 hibernate.use_identifier_rollback 属性,其默认值为 false,若把它设为 true,将改变 delete() 方法的运行行为:delete() 方法会把持久化对象或游离对象的 OID 设置为 null,使它们变为临时对象。这样程序就可以重复利用这些对象了

参考:http://www.myexception.cn/software-architecture-design/1996251.html

时间: 2024-11-03 21:09:50

hibernate5(8)操纵对象入门[3]操控对象封装方法的相关文章

hibernate5(6)操纵对象入门[1]Session缓存

java对象在JVM中的存活条件 在java中,我们使用User user = new User();来创建一个java对象时,JVM会为其分配一块内存空间,此时,这个对象被变量"user"引用,那么它就会一直存在于内存中,而如果我们我们的"引用者user"升级了,User user = new VipUser().那么原来new User()不再被任何变量引用,它就会结束自己的生命周期,然后会被JVM的智能垃圾回收期回收处理,以免再占用内存. 从以上分析,我们知道

java基础 第一章 对象入门

第1章 对象入门 "为什么面向对象的编程会在软件开发领域造成如此震憾的影响?" 面向对象编程(OOP)具有多方面的吸引力.对管理人员,它实现了更快和更廉价的开发与维护过程.对分析与设计人员,建模处理变得更加简单,能生成清晰.易于维护的设计方案.对程序员,对象模型显得如此高雅和浅显.此外,面向对象工具以及库的巨大威力使编程成为一项更使人愉悦的任务.每个人都可从中获益,至少表面如此. 如果说它有缺点,那就是掌握它需付出的代价.思考对象的时候,需要采用形象思维,而不是程序化的思维.与程序化设

1.JAVA 编程思想——对象入门

对象入门 欢迎转载,转载请标明出处:    http://blog.csdn.net/notbaron/article/details/51040219 如果学JAVA,没有读透<JAVA 编程思想>这本书,实在不好意思和别人说自己学过JAVA.鉴于此,蛤蟆忙里偷闲,偷偷翻看这本传说中的牛书. 面向对象编程OOP具有多方面吸引力.实现了更快和更廉价的开发与维护过程.对分析与设计人员,建模处理变得更加简单,能生成清晰.已于维护的设计方案. 这些描述看上去非常吸引人的,不过蛤蟆还是没啥印象(至少到

JS搞基指南----延迟对象入门提高资料整理

原文:JS搞基指南----延迟对象入门提高资料整理 JavaScript的Deferred是比较高大上的东西,  主要的应用还是主ajax的应用,  因为JS和nodeJS这几年的普及,  前端的代码越来越多,  各种回调套回调再套回调实在太让人崩溃, 所以就从后端拖了一个延迟对象这货, 用来解决回调地狱这个问题 .  我们使用ajax的时候多数都是为ajax添加回调 ,然后异步向服务器发送请求, 比如如下原生的XHR代码: <!DOCTYPE html PUBLIC "-//W3C//D

JS入门之ActiveXObject对象(转载)

JS入门之ActiveXObject对象 此对象提供自动化对象的接口.   function ActiveXObject(ProgID : String [, location : String]) 参数 ProgID 必选.形式为"serverName.typeName"的字符串,其中 serverName 是提供对象的应用程序的名称,typeName 是要创建的对象的类型或类. location 可选项.要在其中创建对象的网络访问器的名称. 备注 通常,自动化服务器会提供至少一种对

读TIJ -1 对象入门

<Thinking In Java·第 1 章对象入门> 第 1 章约20页,是对面向对象的程序设计(OOP)的一个综述.按照其前言所述:"其中包括对"什么是对象"之类的基本问题的回答,并讲述了接口与实现.抽象与封装.消息与函数.继承与合成以及非常重要的多形性的概念.这一章会向大家提出一些对象创建的基本问题,比如构建器.对象存在于何处.创建好后把它们置于什么地方以及魔术般的垃圾收集器(能够清除不再需要的对象).要介绍的另一些问题还包括通过违例实现的错误控制机制.反

jQuery入门和DOM对象

jQuery入门和DOM对象 1.开发准备 1. 下载的版本: jquery-3.3.1.min.js :压缩版,发布版84.8KB jquery-3.3.1.js :常规版,开发版265KB 2. 开发工具: ? hbuilder webstrom(推荐) dreamweaver idea ? notepad++ 3. 使用: ? 引入jQuery html中 如果出错,不提示! 如果调试工具(F12)没有错误提示,但显示效果不一致,考虑html错误 常见错误: 引入js库时 必须是 <scr

java 对象入门

对象的五大特征 (1)所有东西都是对象.可将对象想象成一种新型变量;它保存着数据,但可要求对自身进行操作.理论上讲, 可从要解决的问题身上提出所有概念性的组件,然后再程序中将其表达为一个对象. (2)程序是一大堆对象的组合;通过消息传递,各对象知道自己该做什么.为了向对象发出请求,需向那个对象 "发送一个消息".更具体地讲,可将消息想象为一个调用请求,它调用的是从属于目标对象的一个子列程或 函数. (3)每个对象都有自己的存储空间,可容纳其他对象.或者说,通过封装现有对象,可制作新型对

[js对象]JS入门之arguments对象

每天一对象,JS天天见,今天我们来看看arguments对象及属性.arguments对象不能显式创建,arguments对象只有函数开始时才可用.函数的 arguments 对象并不是一个数组,访问单个参数的方式与访问数组元素的方式相同.索引 n 实际上是 arguments 对象的 0…n 属性的其中一个参数. 下面的示例演示了 arguments 对象的用法,arguments对象和Function是分不开的. function ArgTest(a, b){ var i, s = "The