hibernate状态_Hibernate状态的自然身份证
hibernate状态
自然ID是可以唯一标识实体的一个或一组属性。 我们最多可以为一个实体定义一个自然ID。 当Hibernate在实体映射文件中看到natural-id标记时,它会自动在构成natural-id的属性上创建唯一且非空的约束。 首先,让我们看一下简单和复合自然ID的示例。
简单的自然ID:一个人可以通过其选民ID进行唯一标识。 因此,我们可以说这可能来自他的自然身份。
<!-- Version 1 -->
<hibernate-mapping package="com.pramati.model"><class name="Person" table="PERSON"><id name="id" column="ID"><generator class="native"/></id><natural-id><property name="voterId" type="string" column="VOTER_ID"/></natural-id><property name="name" type="string" column="NAME"/><!-- Other properties -->
</class>
</hibernate-mapping>
复合自然ID:电话号码,即标准代码和固定电话号码的组合,可以形成个人实体的自然ID。
<!-- Version 2 -->
<hibernate-mapping package="com.pramati.model"><class name="Person" table="PERSON"><id name="id" column="ID"><generator class="native"/></id><natural-id><property name="stdCode" type="string" column="STD_CODE"/><property name="landlineNumber" type="string" column="LANDLINE_NUMBER"/></natural-id><property name="name" type="string" column="NAME"/><!-- Other properties -->
</class>
</hibernate-mapping>
因此,Hibernate在stdCode和landlineNumber上创建了一个非空约束。 这些属性对于个人实体应该是唯一的。
默认情况下,自然ID是不可变的。 因此,假设您尝试从数据库中加载人员实体并更改构成自然ID的任何属性,则Hibernate将引发异常。 例如,我们已加载Person并尝试在活动会话中修改其landlineNumber / stdcode,这是我们会得到的例外:
org.hibernate.HibernateException:: An immutable natural identifier
of entity com.pramati.model.Person was altered from abc to xyz
Hibernate 4.1提出了通过bean的natural-id加载实体的功能。 到目前为止,会话缓存将缓存通过当前会话中的get / load加载的对象。 现在,默认情况下还将缓存使用natural-id加载的对象。 以下是会话API的最新功能:
public NaturalIdLoadAccess byNaturalId(String entityName);
public NaturalIdLoadAccess byNaturalId(Class entityClass);public SimpleNaturalIdLoadAccess bySimpleNaturalId(String entityName);
public SimpleNaturalIdLoadAccess bySimpleNaturalId(Class entityClass);
我们可以通过自然ID加载类的实例,如下所示:
// In case of version 1 defined above:
Person person = (Person)session.byNaturalId(Person.class ).using( "voterID", "ZAAXDFT435" ).load();// For Version 1, this can be simplified as:
Person person = (Person)session.bySimpleNaturalId(Person.class ).load("ZAAXDFT435");// In case of version 2 defined above:
Person person = (Person)session.byNaturalId(Person.class ).using("stdCode", "040").using("landlineNumber","2345678").load();
请注意,负载返回的实体不仅是代理,而且是实际实体本身。 如果要获取代理,则必须使用getReference()代替load(),如下所示:
session.byNaturalId(Person.class )
.using("stdCode", "040")
.using("landlineNumber","2345678")
.getReference();
为了保持一致性,新方法也可用于基于标识符的加载。
public IdentifierLoadAccess byId(String entityName);
public IdentifierLoadAccess byId(Class entityClass);
因此,我们可以使用session.byId(Person.class).getReference(id)代替session.load(Person.class,id)。 而不是session.get(Person.class,id)我们可以使用session.byId(Person.class).load(id)
当我们使用查询缓存时,自然ID也很有用。 查询缓存通常没有那么有用,因为它经常变得无效。 假设事件序列如下:
方案1:
1.使用实体natural-id中的属性进行HQL查询以加载人员A。 查询也被缓存,即query.setCacheable(true)
2.将另一个人B插入到人表中。
3.现在,使用与步骤1中相同的查询再次加载A。 问题是:在步骤3中,将进行新的数据库调用以从“人”表中获取A。 是还是不是?
答案是肯定的。 发生的事情是Hibernate在内部维护一个时间戳缓存。 这个时间戳缓存记录特定的Hibernate受管表被修改的时间。 现在在步骤(3),Hibernate看到它是一个缓存的查询。 但是在返回存在于缓存中的实体之前,它会验证缓存的结果相对于表修改时间是否较旧。 现在,由于在缓存后修改了表,因此Hibernate再次进行了新查询。
为了进一步了解这一点,让我们考虑以下情形:让我们只在名称为Rama的Person表中进行记录
方案2:
一个。 执行缓存的查询以获取名称与“ Rama”匹配的人员列表:“来自人员名称为“ Rama”的人员”
b。 也将记录插入名称也为“ Rama”的“个人”中。 这不是问题,因为名称未定义为唯一属性
C。 现在,再次执行步骤(a)中的查询。
最初在步骤(a),我们仅获得记录。 但是在步骤(c)中,即使结果被缓存,Hibernate也会再次命中数据库。 这是由于时间戳缓存无效而发生的。 Hibernate只是在从高速缓存返回实体之前检查表是否已被修改。 但是,无论是更新,插入还是后续操作,都不会影响表的更新方式。
但是在我们看过的前一种情况下,此验证检查似乎完全不相关,因为插入的记录与加载的实体无关。 如果我们使用自然ID来获取实体,则可以绕过此检查。 使用natural-id时,可以保证即使修改数据库后结果也不会改变。 早些时候,当我们不支持使用自然ID加载实体时,我们在Criteria API中提供了使用自然ID的规定。 我们可以在方案1的步骤(1)和(3)中使用以下内容
session.createCriteria(Person.class).add(Restrictions.naturalId().set("stdCode", person.getStdCode()).set("landlineNumber", person.getLandlineNumber())).setCacheable(true).uniqueResult();
当使用自然ID来获取实体时,时间戳缓存检查将被绕过。 因此,现在,如果我用此条件而不是查询替换第一种情况的步骤(1)和(3),则数据库只会被命中一次。 如果我们使用Restrictions.eq而不是Restrictions.naturalId,数据库将被命中两次。 另外,如果您使用的是最新版本的Hibernate,我们可以使用新的API代替构建标准。
翻译自: https://www.javacodegeeks.com/2013/10/natural-ids-in-hibernate.html
hibernate状态
hibernate状态_Hibernate状态的自然身份证相关推荐
- Rhythmk 学习 Hibernate 02 - Hibernate 之 瞬时状态 离线状态 持久化状态 三状态
by:rhythmk.cnblogs.com 1.Hibernate 三种状态: 1.1.三种定义(个人理解,不一定准确): 瞬时状态(transient): 不被session接管,且不存在 ...
- hibernate 三种状态的转换
一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...
- SSH框架之-hibernate 三种状态的转换
一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...
- Hibernate对象的状态和映射
一. Hibernate对象的状态 实体对象的三种状态: 1) 暂态(瞬时态)(Transient)---实体在内存中的自由存在,它与数据库的记录无关. po在DB中无记录(无副本),po和sessi ...
- Hibernate三种状态(Transient、Persistent、Detached)各种保存(save,persist,update,saveOrUpdte,merge,flush,lock)区别
转载地址:http://www.2cto.com/kf/201212/178604.html 一.三种状态(Transient.Persistent.Detached) 在Hibernate中有三种状 ...
- 【设计模式】享元模式 简介 ( 定义 | 对象池 | 内部状态 | 外部状态 | 适用场景 | 相关角色 )
文章目录 I . 享元模式 简介 II . 享元模式 内部状态 和 外部状态 III . 享元模式 适用场景 IV . 享元模式 优缺点 V . 享元模式 相关模式 VI . 享元模式 相关角色 I ...
- 有状态,无状态对象是什么概念
基本概念: 有状态就是有数据存储功能.有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的.在不同方法调用间不保留任何状态. 无状态就是一次操作,不能保存数据 ...
- Flink 状态管理:算子状态、键值分区状态、状态后端、有状态算子的扩缩容
文章目录 状态管理 算子状态 键值分区状态 状态后端(State Backends) 有状态算子的扩缩容 状态管理 通常意义上,函数里所有需要任务去维护并用来计算结果的数据都属于任务的状态,可以把状态 ...
- 事务的状态(状态模式)
[0]README 0.1)本文部分文字描述转自 "head first设计模式",旨在学习 事务的状态(状态模式) 的基础知识: [1]应用场景一 1.1)还记得成都市各大高校 ...
最新文章
- 模拟/usaco 1.1.4 Broken Necklace
- [c、c++]宏中#和##的用法(zz)
- java 字母大写_Java字母大小写转换的方法
- LwIP应用开发笔记之二:LwIP无操作系统UDP服务器
- 【转】Java和C++的区别有哪些?
- 618技术特辑(三)直播带货王,“OMG买它”的背后,为什么是一连串技术挑战?
- java自动类型转换与强制类型转换
- 文字阴影(HTML、CSS)
- 设计模式之GOF23外观模式
- Dubbo集群容错策略源码分析
- 永中office linux卸载,永中office Linux版
- 解除电脑宽带限制,提升电脑网速
- ios快捷指令 python_手把手教你使用 iOS 效率神器 「快捷指令」
- 多目标优化 MOP (二):遗传算法 SPEA2 2001
- 不讨老婆之“不亦快哉”(三十三则)(李敖)
- 对中国四大名著--红楼梦 使用jieba进行分词处理 排除去停词 统计完整词频并按降序排列 前20词绘制词云图
- 并发编程五:java并发线程池底层原理详解和源码分析
- 三点水加一个必须的必
- WordPress 元老 Alex King 逝世
- 基于java+ssm的家庭理财系统