hibernate自动配置_Hibernate自动冲洗的黑暗面

hibernate自动配置

介绍

既然我已经描述了JPA和Hibernate刷新策略的基础知识 ,我就可以继续阐明Hibernate的AUTO刷新模式的令人惊讶的行为。

并非所有查询都会触发会话刷新

许多人会认为Hibernate 总是在执行任何查询之前先刷新Session。 虽然这可能是一种更直观的方法,并且可能更接近JPA的AUTO FlushModeType ,但是Hibernate尝试对其进行优化。 如果当前执行的查询不会命中未决SQL INSERT / UPDATE / DELETE语句,则不严格要求刷新。

如参考文档中所述,AUTO刷新策略有时可能在执行查询之前同步当前持久性上下文。 如果框架作者选择将其命名为FlushMode.SOMETIMES,那将更加直观。

JPQL / HQL和SQL

与许多其他ORM解决方案一样,Hibernate提供了一种非常基于SQL-92语法的有限实体查询语言( JPQL / HQL )。

当前数据库方言将实体查询语言转换为SQL,因此它必须在不同的数据库产品中提供相同的功能。 由于大多数数据库系统都是SQL-92投诉,因此实体查询语言是最常见的数据库查询语法的抽象。

虽然您可以在许多用例(选择实体,甚至是投影)中使用实体查询语言,但有时其有限功能与高级查询请求不匹配。 每当我们想要利用某些特定的查询技术时,例如:

  • 视窗功能
  • 数据透视表
  • 常用表表达式

我们别无选择,只能运行本机SQL查询。

Hibernate是一个持久性框架。 Hibernate从未打算取代SQL。 如果在本机查询中更好地表达某些查询,那么就不应该在数据库可移植性的高度上牺牲应用程序的性能。

自动冲洗和HQL / JPQL

首先,我们将测试将要执行HQL查询时AUTO刷新模式的行为。 为此,我们定义了以下不相关的实体:

同花顺

该测试将执行以下操作:

  • 一个人将被坚持。
  • 选择用户不应触发刷新。
  • 查询人员时,AUTO刷新应触发实体状态转换同步(应在执行选择查询之前执行人员INSERT)。
Product product = new Product();
session.persist(product);
assertEquals(0L,  session.createQuery("select count(id) from User").uniqueResult());
assertEquals(product.getId(), session.createQuery("select p.id from Product p").uniqueResult());

提供以下SQL输出:

[main]: o.h.e.i.AbstractSaveEventListener - Generated identifier: f76f61e2-f3e3-4ea4-8f44-82e9804ceed0, using strategy: org.hibernate.id.UUIDGenerator
Query:{[select count(user0_.id) as col_0_0_ from user user0_][]} 
Query:{[insert into product (color, id) values (?, ?)][12,f76f61e2-f3e3-4ea4-8f44-82e9804ceed0]} 
Query:{[select product0_.id as col_0_0_ from product product0_][]}

如您所见,用户选择尚未触发会话刷新。 这是因为Hibernate会根据挂起的表语句检查当前查询空间。 如果当前正在执行的查询与未刷新的表语句不重叠,则可以安全地忽略刷新。

HQL甚至可以检测产品冲洗:

  • 子选择
    session.persist(product);
    assertEquals(0L,  session.createQuery("select count(*) " +"from User u " +"where u.favoriteColor in (select distinct(p.color) from Product p)").uniqueResult());

    导致正确的冲洗调用:

    Query:{[insert into product (color, id) values (?, ?)][Blue,2d9d1b4f-eaee-45f1-a480-120eb66da9e8]} 
    Query:{[select count(*) as col_0_0_ from user user0_ where user0_.favoriteColor in (select distinct product1_.color from product product1_)][]}
  • 或theta风格的连接
    session.persist(product);
    assertEquals(0L,  session.createQuery("select count(*) " +"from User u, Product p " +"where u.favoriteColor = p.color").uniqueResult());

    触发预期的冲洗:

    Query:{[insert into product (color, id) values (?, ?)][Blue,4af0b843-da3f-4b38-aa42-1e590db186a9]} 
    Query:{[select count(*) as col_0_0_ from user user0_ cross join product product1_ where user0_.favoriteColor=product1_.color][]}

它起作用的原因是因为已将实体查询解析并转换为SQL查询。 Hibernate无法引用不存在的表,因此它始终知道HQL / JPQL查询将命中的数据库表。

因此,Hibernate仅知道我们在HQL查询中显式引用的那些表。 如果当前待处理的DML语句暗示数据库触发器或数据库级联,则Hibernate将不会意识到这些。 因此,即使对于HQL,AUTO刷新模式也可能导致一致性问题。

自动刷新和本机SQL查询

当涉及本地SQL查询时,事情变得越来越复杂。 Hibernate无法解析SQL查询,因为它仅支持有限的数据库查询语法。 许多数据库系统提供了超越Hibernate Entity Query功能的专有功能。

使用本机SQL查询查询Person表不会触发刷新,从而导致不一致问题:

Product product = new Product();
session.persist(product);
assertNull(session.createSQLQuery("select id from product").uniqueResult());
DEBUG [main]: o.h.e.i.AbstractSaveEventListener - Generated identifier: 718b84d8-9270-48f3-86ff-0b8da7f9af7c, using strategy: org.hibernate.id.UUIDGenerator
Query:{[select id from product][]} 
Query:{[insert into product (color, id) values (?, ?)][12,718b84d8-9270-48f3-86ff-0b8da7f9af7c]}

新保留的产品仅在事务提交期间插入,因为本机SQL查询未触发刷新。 这是主要的一致性问题,许多开发人员很难调试甚至无法预见。 这是始终检查自动生成SQL语句的另一个原因。

即使对于命名的本机查询,也会观察到相同的行为:

@NamedNativeQueries(@NamedNativeQuery(name = "product_ids", query = "select id from product")
)
assertNull(session.getNamedQuery("product_ids").uniqueResult());

因此,即使预加载了SQL查询,Hibernate也不会提取关联的查询空间以使其与未决的DML语句匹配。

否决当前的冲洗策略

即使当前会话定义了默认的刷新策略,您也可以始终基于查询覆盖它。

查询刷新模式

ALWAYS模式将在执行任何查询(HQL或SQL)之前刷新持久性上下文。 这次,Hibernate没有应用优化,所有待处理的实体状态转换都将与当前数据库事务同步。

assertEquals(product.getId(), session.createSQLQuery("select id from product").setFlushMode(FlushMode.ALWAYS).uniqueResult());

指示Hibernate应该同步哪些表

您还可以在当前正在执行SQL查询上添加同步规则。 然后,Hibernate将知道在执行查询之前需要同步哪些数据库表。 这对于二级缓存也很有用。

assertEquals(product.getId(), session.createSQLQuery("select id from product").addSynchronizedEntityClass(Product.class).uniqueResult());

结论

自动刷新模式非常棘手,并且在查询基础上解决一致性问题是维护人员的噩梦。 如果决定添加数据库触发器,则必须检查所有Hibernate查询,以确保它们最终不会针对过时的数据运行。

我的建议是使用ALWAYS刷新模式,即使Hibernate作者警告我们:

这种策略几乎总是不必要且效率低下的。

不一致有时是一些过早冲洗的问题。 当混合DML操作和查询可能会导致不必要的刷新时,这种情况很难缓解。 在会话事务期间,最好在事务开始时(当没有待处理的实体状态转换要同步时)和事务结束时(无论如何将刷新当前持久性上下文)执行查询。

实体状态转换操作应在事务结束时进行,以尽量避免将它们与查询操作交错(因此避免过早的刷新触发器)。

翻译自: https://www.javacodegeeks.com/2014/08/the-dark-side-of-hibernate-auto-flush.html

hibernate自动配置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

slf4j注解log报错_SpringBoot自定义日志注解,用于数据库记录操作日志,你用过吗?...

大家好,我是程序员7歌!今天我将为大家讲解如何通过自定义注解记录接口访问日志。一般的开发中,有两种方式可以记录日志信息,第一种:把接口日志信息保存到日志文件中,第二种:把接口操作日志保存到…

java applet audion_java applet audion

①希罗尤尔和他的飞翼敢达也有着不少拥趸,让我们期待这位美少年在《敢达决战》中的表现吧。②颜值时代,浏览器皮肤也不能输360浏览器耳目一新的设计,高清精美的壁纸,让你上网时更添一份好心情。软件使用1、支持游戏小号2、优化小程…

处理Java异常的10种最佳实践

在本文中,我们将看到处理Java异常的最佳实践。 用Java处理异常不是一件容易的事,因为新手很难理解,甚至专家级开发人员也可能浪费时间讨论应该抛出或处理哪些Java异常。 因此,最大的开发公司对如何使用它们有一套规则。 如果您是…

markdown 流程图_Markdown 进阶技能:用代码画流程图(编程零基础也适用)

这篇文章主要介绍流程图基础以写代码的方式画流程图相比于使用画图工具拖拽画图,用代码画图有什么好处?首先,这种方式非常轻便,无需安装复杂的画图应用。Typora 等多种 Markdown 编辑器自带有画图扩展(这也是 Markdown…

java jtree_Java JTree

Java JTree1 Java JTree的介绍JTree类用于显示树结构数据或层次结构数据。JTree是一个复杂的组件。它的最顶部有一个“根节点”,它是树中所有节点的父节点。它继承了JComponent类。2 Java JTree的声明我们来看一下javax.swing.JTree类的声明。public class JTree ex…

akka和rabbitmq_Akka Notes –演员记录和测试

akka和rabbitmq在前两部分( 一 , 二 )中,我们简要讨论了Actor以及消息传递的工作方式。 在这一部分中,让我们看一下如何修复并记录我们的TeacherActor 。 回顾 这就是我们上一部分中的Actor的样子: class…

完数c++语言程序_C语言经典100题(19)

1上期答案揭晓首先给大家看看上一篇文章C语言经典100题(18)中第三部分编程题的答案:#includeint main(){ int s0,a,n,t; printf("请输入 a 和 n:\n"); scanf("%d%d",&a,&n); ta; while(n>0) { …

PHP怎样表示几时几分,PHP将时间戳转换为刚刚、N分钟前、今天几点几分、昨天几点几分......

自定义函数&#xff1a;<?php date_default_timezone_set(PRC); // 设置时区&#xff0c;如果已经设置可以删除function timeFormat( $timestamp ) {$curTime time();$space $curTime - $timestamp;if($space < 60) { // 一分钟以内$string "刚刚";return …

古巴:为生产做准备

“它可以在我的本地机器上运行&#xff01;” 如今&#xff0c;这听起来像模因&#xff0c;但仍然存在“开发环境与生产环境”的问题。 作为开发人员&#xff0c;您应始终牢记&#xff0c;您的应用程序有一天将在生产环境中开始运行。 在本文中&#xff0c;我们将讨论一些特定于…

php重载,PHP 重载

PHP 重载一个类中的方法与另一个方法同名&#xff0c;但是参数不同&#xff0c;这种方法称之为重载方法。很遗憾因为 PHP 是弱类型的语言&#xff0c; 所以在方法的参数中本身就可以接收不同类型的数据&#xff0c;又因为 PHP 的方法可以接收不定个数的参数&#xff0c;所以在 …

平板安装python_在CentOS上安装Python3的三种方法

Centos7默认自带了Python2.7版本,但是因为项目需要使用Python3.x你可以按照此文的三个方法进行安装.注&#xff1a;本文示例安装版本为Python3.5&#xff0c;一、Python源代码编译安装安装必要工具 yum-utils &#xff0c;它的功能是管理repository及扩展包的工具 (主要是针对r…

hibernate脏数据_Hibernate脏检查的剖析

hibernate脏数据介绍 持久性上下文使实体状态转换入队 &#xff0c;该实体状态转换在刷新后转换为数据库语句。 对于托管实体&#xff0c;Hibernate可以代表我们自动检测传入的更改并安排SQL UPDATE。 这种机制称为自动脏检查 。 默认的脏检查策略 默认情况下&#xff0c;Hibe…

python查询sql_Python处理SQL语句(提供SQL查询平台使用)

在搞公司的SQL查询(MySQL)平台时&#xff0c;需要对用户查询SQL进行条数限制&#xff0c;默认是在配置文件中配置一个“limit 1000”这样的参数。最自然想到的就是对用户通过web传入的SQL做处理&#xff0c;默认加上limit参数。这样一来就有这么几个问题需要处理&#xff1a;1…

php组成,php接口有几部分组成?

程序接口&#xff0c;由一套陈述、功能、选项、其它表达程序结构的形式、以及程序师使用的程序或者程序语言提供的数据组成PHP接口(interface)的特点1、接口的方法必须是公开的。2、接口的方法默认是抽象的&#xff0c;所以不在方法名前面加abstract。3、接口可以定义常量&…

AWS Elasticsearch后模式

因此&#xff0c;碰巧我们在SaaS版本的LogSentinel上遇到了生产问题–我们的Elasticsearch停止了对新数据编制索引。 由于Elasticsearch只是辅助存储&#xff0c;因此没有数据丢失&#xff0c;但这给我们的客户带来了一些问题&#xff08;他们无法在其仪表板上看到实时数据&…

python设置word背景色_Python数据可视化:WordCloud入门

WordCloud是一种很好的展现数据的方式&#xff0c;网上也有不少小工具和在线网页。但是有些不支持中文&#xff0c;有些安装复杂&#xff0c;所以决定用Python实现。主要参考官网&#xff0c;通过官网的例子&#xff0c;讲一下WordCloud的制作。主要流程获取内容的路径如果是一…

java 解析日期格式_日期/时间格式/解析,Java 8样式

java 解析日期格式自Java 几乎 开始以来&#xff0c;Java开发人员就通过java.util.Date类&#xff08;自JDK 1.0起&#xff09;和java.util.Calendar类&#xff08;自JDK 1.1起 &#xff09;来处理日期和时间。 在这段时间内&#xff0c;成千上万&#xff08;甚至数百万&#x…

php第三方登录代码,thinkPHP5项目中实现QQ第三方登录功能

本文实例讲述了thinkPHP5项目中实现QQ第三方登录功能。分享给大家供大家参考&#xff0c;具体如下&#xff1a;最近用thinkPHP 5框架做了一个婚纱店的项目&#xff0c;在开发过程中需要用到第三方登录&#xff0c;腾讯官方给的案例是几个文件相互包含实现的&#xff0c;放到tp5…

mac 显示隐藏文件_如何在Mac上显示隐藏文件?苹果mac显示隐藏文件夹方法

与任何操作系统一样&#xff0c;macOS会将重要文件隐藏起来&#xff0c;以防止意外删除它们并因此而损坏系统。但是&#xff0c;在某些情况下&#xff0c;您可能需要在Mac上显示隐藏文件&#xff0c;例如&#xff0c;浏览“ 库”文件夹并清除旧日志&#xff0c;缓存或其他垃圾文…

分布式虚拟跟踪

跟踪提供了对系统的可见性&#xff0c;使开发人员和操作人员可以在运行时观察应用程序。 当系统不断增长并与更多微服务进行交互时&#xff0c;跟踪变得非常有价值。 在这样的环境中&#xff0c;这些痕迹非常棒&#xff0c;可以定位导致性能下降的故障和瓶颈。 在这篇文章中&a…