Hibernate实体对象状态和操作

摘要:
Hibernate提供会话。update()和sessionmerge()方法使更改的自由对象的重新附加会话持久化。当使用merge合并修改时,不应考虑会话中对象的状态。只要操作实例不是从一个会话到另一个会话,就不应使用saveOrUpdate、update和merge操作。

一、Hibernate对象的状态

  • 瞬态(Transient):当一个对象通过new 操作符创建,并且没有和Hibernate的session关联过,就处于瞬态。瞬态的对象在数据库里没有相应的记录和标识符,和普通Object没有区别。
  • 持久化(Persistent):持久化的实例在数据库有对应的记录和标识符,并且在session的范围内,任何对实例的改动都会被持久化到数据库,不需要手动执行update或者delete操作。
  • 游离态(Detached):被持久化过的实例并且session已经关闭就处于游离态。对象的索引仍然存在,可以修改实例后,在某个时间点附着session,变成持久化。一个典型应用场景是:从数据库取出数据后,会话关闭,呈现数据给用户,用户修改数据后,提交数据保存到数据库,这过程叫应用事务。

二、持久化对象

  通过使新创建的对象和session关联,使对象变成持久化,方法有以下两种方式:

  • session.save():save承诺返回标识符(一般为表主键),如果配置的主键生成策略要求insert才能生成,会立刻执行insert语句,而不管操作是否处于事务内。
  • session.persist():不承诺会持久化对象会立刻获得标识符,可能要等到flush才会被分配到标识符。

  对于已经持久化过的实例,数据库有相应的记录,通过session.load()可以加载出持久化对象,需要知道对象的标识符。如果在数据库找不到对应的对象,则会抛出异常。如果为该实例的类配置的proxy,load操作只会返回未初始化的代理,只有真正执行代理方法才会到数据库取数据。

  如果你不确定数据库是否一定存在相应的记录,采用get()操作,它会立刻到数据库查询,找不到记录则返回null。此外,通过传递LockMode,将以特定的锁加载对象(执行select ... for update),如果没有配置cascade=all的级联关系,关联的对象不会被执行到(select...for update)。

  对于已经加载出来的对象,可以通过session.refresh(object)对象的属性和所有关联的集合,这在数据库存在触发器生成对象的某些属性的情景十分有用。

sess.save(cat);
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)

  至于Hibernate如何从数据库中加载对象,这与抓取策略有关(Fetching strategy),详细情况抓取策略一章。

三、修改游离态的对象

  前面说过,很多应用场景是:在一个事务中读取数据,然后在UI上呈现给用户修改,最后在新的事务中保存更改。读取数据出来后,到用户提交之前,对象可以认为的游离态(真实情况UI呈现时对象已经消亡,提交数据时会根据提交的数据创建对象,这时对象就是游离态)。Hibernate提供session.update()和session.merge()方法使更改后的游离态对象重新附着session变为持久化。一个例子:

// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catId);
Cat potentialMate = new Cat();
firstSession.save(potentialMate);

// in a higher layer of the application
cat.setMate(potentialMate);

// later, in a new session
secondSession.update(cat);  // update cat
secondSession.update(mate); // update mate

  注意,从firstSession取出来的对象cat,不能在执行update之前已经附着secondSession,否则抛出异常。也就是说用来update的session要确定不能包含有着同样标识符的持久化实例。

  使用merge来合并修改则不要考虑对象在session的状态。

  lock方法也允许应用重新关联对象和session,条件是对象实例不能被更改过。注意lock也能和不同的lockMode结合实现不同程度的事务隔离。

四、自动检测对象会话状态

  Hibernate提供saveOrUpdate(object)方法实现自动根据被操作的对象的状态执行相应的数据库操作。如果是瞬态对象则执行save操作,如果检测到是游离态(根据标识符)则执行update或者重关联实例。只要操作的实例不是由一个session到另一个session,你都不应该使用saveOrUpdate、update和merge操作。

  saveOrUpdate和update的通用使用场景如下:

  • 应用程序在第一个session中加载对象;
  • 对象在UI中呈现给用户;
  • 用户对对象数据进行了部分修改;
  • 修改后的对象数据被传回业务逻辑层;
  • 应用程序在第二个session里通过调用update来持久化这些更改;

  saveOrUpdate的操作过程如下:

  • 如果对象已经在session中被持久化,什么都不做;
  • 如果session中存在有着同样标识符的其他对象(即有着同样标识符的对象被持久化),抛出异常;
  • 如果对象没有标识符属性,执行save操作;
  • 如果对象被分配了新的标识符,执行save操作;
  • 如果对象是附带版本信息的(通过<version>或<timestamp>),并且版本属性值表名这是新的对象,执行save操作;
  • 其他情况执行update操作;

  merge操作以前两个很不同:

  • 如果session里面已经关联了有同样标识符的对象,则复制被操作对象的数据到已经持久化的对象;
  • 如果当前session没有关联到持久化对象(依据标识符判断?),则尝试数据库加载进来,又或者创建一个新的持久化对象;
  • 返回持久化对象;
  • 被操作的对象没有和session关联,保持游离态;

免责声明:文章转载自《Hibernate实体对象状态和操作》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Java#HttpClien详解sqlserver docker 安装部署试用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Oracle 11g与12c的审计详解

最近遇到一些脚本诱发的审计相关BUG,感觉有必要重新梳理一下11g与12c的审计模式,于是根据官网修正了一下以前的一篇笔记这里发出来。 一、审计功能的开启: SQL> show parameter audit --主要有以下四个参数: AUDIT_TRAIL(default:DB) AUDIT_FILE_DEST(default:ORACLE_...

netty发送和接收数据handler处理器

netty发送和接收数据handler处理器 主要是继承 SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter   一般用netty来发送和接收数据都会继承SimpleChannelInboundHandler和ChannelInboundHandlerAdapter这两个抽象类,那么这两个...

从备份文件bak中识别SQL Server的版本

原文:https://www.cnblogs.com/Rawls/p/10726010.html SQLServer 的备份文件是以.bak 为后缀的文件,如果想要通过备份文件查看数据库版本,通常的做法就是把数据库还原,但是在还原的过程,如果不是相同的数据库版本,就会导致无法还原; 在数据库中,低版本的备份文件是可以还原到高版本的数据库中,高的就不可以了,...

麻雀虽小,五脏俱全。基于Asp.net core + Sqlite 5分钟快速上手一个小项目

虽然该方法不会用在实际开发中,但该过程对于初学者还是非常友好的,真应了麻雀虽小,五脏俱全这句话了。好了不多废话了,直接开始!! 1.建立一个名为test的Asp.net core web应用程序 这一部分的目的是建立项目,并使用MVC框架。 2.导入依赖项(sqlite数据库 与 EF core) 这一部分的操作目的是可以让我们的项目可以使用操作数据库的...

2、架构设计 --短信平台开发

二、架构设计1、网络架构设计 由于单位网络问题,平常使用的内网(管理网)不能直接连接互联网,需要由外联网中介。同时由于安全策略的缘故,外联网与管理网是单向访问(外联网不能访问管理网,管理网可以访问外联网),所以数据库只能放在外联网上。 网站架构图如下 2、下行短信发送 这个流程画时序图比流程图更直观一点。 首先第三方系统调用短信平台的WebServi...

Android 让你的 Room 搭上 RxJava 的顺风车 从重复的代码中解脱出来

什么是 Room ? 谷歌为了帮助开发者解决 Android 架构设计问题,在 Google I/O 2017 发布一套帮助开发者解决 Android 架构设计的方案:Android Architecture Components,而我们的 Room 正是这套方案的两大模块之一。 定义:数据库解决方案 组成:Database、Entity、DAO 为...