Hibernate脏数据检查

脏数据检查:

   什么是脏数据?脏数据并不是废弃和无用的数据,而是状态前后发生变化的数据。我们看下面的代码:

 Transaction tx=session.beginTransaction();

 User user=(User)session.load(User.class,”1”);//从数据库中加载符合条件的数据

 user.setName(“zx”);//改变了user对象的姓名属性,此时user对象成为了所谓的“脏数据”

 tx.commit();

 当事务提交时,Hibernate会对session中的PO(持久化对象)进行检测,判断持久化对象的状态是否发生了改变,如果发生了改变就会将改变更新到数据库中。这里就存在一个问题,Hibernate如何来判断一个实体对象的状态前后是否发生了变化。也就是说Hibernate是如何检查出一个数据已经变脏了。

通常脏数据的检查有如下两种办法:

 A、数据对象监控:

数据对象监控是通过拦截器对数据对象的setter方法进行监控来实现的,这类似于数据库中的触发器的概念,当某一个对象的属性调用了setter方法而发生了改变,这时拦截器会捕获这个动作,并且将改属性标志为已经改变,在之后的数据库操作时将其更新到数据库中。这个方法的优点是提高了数据更新的同步性,但是这也是它的缺点,如果一个实体对象有很多属性发生了改变,势必造成大量拦截器回调方法的调用,这些拦截器都是通过Dynamic
Proxy或者CGLIB实现的,在执行时都会付出一定的执行代价,所以有可能造成更新操作的较大延时。

   B、数据版本比对:

这种方法是在持久化框架中保存数据对象的最近读取版本,当提交数据时将提交的数据与这个保存的版本进行比对,如果发现发生了变化则将其同步跟新到数据库中。这种方法降低了同步更新的实时性,但是当一个数据对象的很多属性发生改变时,由于持久层框架缓存的存在,比对版本时可以充分利用缓存,这反而减少了更新数据的延迟。

在Hibernate中是采用数据版本比对的方法来进行脏数据检查的,我们结合下面的代码来讲解Hibernate的具体实现策略。

Transaction tx=session.beginTransaction();

 User user=(User)session.load(User.class,”1”);

 user.setName(“zx”);

 tx.commit();

当调用tx.commit();时好戏就此开场,commit()方法会调用session.flush()方法,在调用flush()方法时,会首先调用flushEverything()来进行一些预处理(如调用intercepter,完成级联操作等),然后调用flushEntities()方法,这个方法是进行脏数据检查的关键。

在继续讲解之前,我要先来介绍一个内部数据结构EntityEntry,EntityEntry是从属于SessionImpl(Session接口的实现类)的内部类,每一个EntityEntry保存了最近一次与数据库同步的实体原始状态信息(如:实体的版本信息,实体的加锁模式,实体的属性信息等)。除了EntityEntry结构之外,还存在一个结构,这个结构称为EntityEntries,它也是SessionImpl的内部类,而且是一个Map类型,它以”key-value”的形式保存了所有与当前session实例相关联的实体对象和原始状态信息,其中key是实体对象,value是EntityEntry。而flushEntities()的工作就是遍历entityEntities,并将其中的实体对象与原始版本进行对比,判断实体对象是否发生来了改变。flushEntities()首先会判断实体的ID是否发生了改变,如果发生了改变则认为发生了异常,因为当前实体与EntityEntry的对应关系非法。如果没有发生异常,而且经过版本比对判断确实实体属性发生了改变,则向当前的更新任务队列中加入一个新的更新任务,此任务将在将在session.flush()方法中的execute()方法的调用中,转化为相应的SQL语句交由数据库去执行。最后Transaction将会调用当前session对应的JDBC
Connection的commit()方法将当前事务提交。

脏数据检查是发生在显示保存实体对象时,所谓显示保存是指在代码中明确使用session调用save,update,saveOrupdate方法对实体对象进行保存,如:session.save(user);但是有时候由于级联操作的存在,会产生一个问题,比如当保存一个user对象时,会根据user对象的状态来对他所关联的address对象进行保存,但是此时并没有根据级联对象的显示保存语句。此时需要Hibernate能根据当前对象的状态来判断是否要将级联对象保存到数据库中。此时,Hibernate会根据unsaved-value进行判断。Hibernate将首先取出目标对象的ID,然后将ID与unsaved-value值进行比较,如果相等,则认为实体对象尚未保存,进而马上将进行保存,否则,则认为实体对象已经保存,而无须再次进行保存。比如,当向一个user对象新加入一个它所关联的address对象后,当进行session.save(user)时,Hibernate会根据unsaved-value的值判断出哪个address对象需要保存,对于新加入的address对象它的id尚未赋值,以此为null,与unsaved-value值相等,因此Hibernate会将其视为未保存对象,生成insert语句加以保存。如果想使用unsaved-value必须如下配置address对象的id属性:

……

<id name=”id” type=”java.lang.Integer” unsaved-value=”null”>

 <generator class=”increment”/>

</id>

……

时间: 2024-10-10 05:16:21

Hibernate脏数据检查的相关文章

Angular DirtyChecking(脏值检查) $watch, $apply, $digest

Dirty Checking (脏值检查) Digest cycle and $scope Digest cycle and $scope First and foremost, AngularJS defines a concept of a so-called digest cycle. This cycle can be considered as a loop, during which AngularJS checks if there are any changes to all t

解决hibernate保存数据到mysql中出现乱码问题

今天使用hibernate保存数据到mysql中,发现出现乱码问题,经过检查,发现接收到的是正确中文,说明客户端浏览器将中文编码发送到服务器过程中无乱码问题,后来查找资料: 首先要告诉数据库要插入的字符串的字符集,mysql 默认使用的字符集是 latin1.我要保存的字符串是 UTF-8 编码的(字符集是 Unicode),所以包含这个字段的表应该使用 UTF-8 编码. 这里有几种解决办法. 1.在建立数据库的时候指定数据库的字符集编码,这样,这个数据库的所有表都会默认使用数据库的字符集编码

(二)脏数据的预防及处理

(啊···我的排版好垃圾·····) 如何处理已产生的脏数据?有那么多预防脏数据产生的方法,但相信脏数据的产生还是在所难免的.脏数据一旦产生,导致的系统行为也是不可预测的,可能无足轻重,也可能暴露非常严重的缺陷.该如何应对产生的脏数据呢? 脏数据产生以后有两种存在形式,一种是已经引起某些问题被发现了,另一种是还不被人知道,不知道哪天会发生什么样的问题. 已经暴露的脏数据 首要的是对数据的快速修复,让系统恢复正常运转.对于专业的脏数据处理可以了解一下数据清洗(Data cleaning)技术.咱们

。。。Hibernate 查询数据 事务管理。。。

在Hibernate中,查询数据的时候,可能会需要事务的管理,为什么呢?因为在查询数据库的时候,Hibernate将数据从数据库里面查询出来之后,会先把数据放入Hibernate的session缓存里,下次你再次发送同一个请求的时候,Hibernate会先从缓存里面查数据,如果发现有这样的数据,OK,那就直接把这个数据拿过去显示,如果没有的话,才会到数据库里面查询显示.这个就是说,在页面显示的数据是A,到后台把数据改为B,现在前台刷新,则还会显示数据A,不会显示数据B的原因!

脏数据

从广义上看,脏数据是指没有进行过数据预处理而直接接收到的.处于原始状态的数据: 从狭义上看,是不符合研究要求,以及不能够对其直接进行相应的数据分析. 脏数据依据不同的分析目的有不同的定义,如在常见的数据挖掘工作中,脏数据是指不完整.含噪声.不一致的数据:而在问卷分析中,脏数据则是指不符合问卷要求的数据. 开发中: 脏数据是指源系统中的数据不在给定的范围内或对于实际业务毫无意义,或是数据格式非法,以及在源系统中存在不规范的编码和含糊的业务逻辑. 在数据库技术中,脏数据在临时更新(脏读)中产生.事务

如何使用R语言解决可恶的脏数据

转自:http://shujuren.org/article/45.html 在数据分析过程中最头疼的应该是如何应付脏数据,脏数据的存在将会对后期的建模.挖掘等工作造成严重的错误,所以必须谨慎的处理那些脏数据. 脏数据的存在形式主要有如下几种情况: 1)缺失值 2)异常值 3)数据的不一致性 下面就跟大家侃侃如何处理这些脏数据. 一.缺失值 缺失值,顾名思义就是一种数据的遗漏,根据CRM中常见的缺失值做一个汇总: 1)会员信息缺失,如身份证号.手机号.性别.年龄等 2)消费数据缺失,如消费次数.

Hibernate的数据查找,添加!

1.首先看一下测试数据库的物理模型 2.测试所需要的Hibernate的jar包 3.数据库的sql /*==============================================================*/ /* DBMS name: MySQL 5.0 */ /* Created on: 2015/7/3 23:17:57 */ /*==============================================================*/ dr

在ASP.NET MVC下有关上传图片脏数据的解决方案

在"在ASP.NET MVC下实现单个图片上传, 客户端服务端双重限制图片大小和格式, 服务端裁剪图片"中,已经实现了在客户端和服务端限制图片大小和格式,以及在服务端裁剪图片.但还有一个重要的话题是需要面对的,那就是图片脏数据问题. 假设用户添加产品信息,并且上传了图片,可之后用户没有点击页面上的添加按钮,这就导致上传图片成为"脏数据",存在着却一直不会被使用.解决这个问题的大致思路是: ○ 在上传图片的时候,把图片保存到一个临时文件夹,或者叫缓存文件夹○ 当用户真

事务 脏数据

关于脏数据比如说,有两个用户A,B同时操作数据库,A开始了一个事务,修改了某行,但还未提交,这个时候,B开始另一个事务,读取了该行,然后A回滚了事务,即修改被取消了,那么,B读取到的那一行数据就是脏数据 上面这句话正确吗?如果事物A未提交,事物B能读到A所修改的数据吗? 如何判断A,B 是否属于同一个事物? 在PL/SQL 中先删一条数据(没有提交)紧接着在查刚才那条数据是查不到的,既然没有提交为什么会查不到呢? 希望各位能详细回答一下,小弟不胜感激. Q:如果事物A未提交,事物B能读到A所修改