jpa命名 多条件查询命名_JPA 2 | 动态查询与命名查询

jpa命名 多条件查询命名

JPA有自己的查询语言,称为JPQL。 JPQL与SQL非常相似,主要区别在于JPQL与应用程序中定义的实体一起使用,而SQL与数据库中定义的表和列名称一起使用。 在定义将对定义的Entity类执行CRUD操作的JPA查询时,JPA为我们提供了多种选择。 这些选项是动态查询,命名查询和条件查询。 这篇文章试图详细介绍每个选项,重点是何时使用每种类型的查询定义,可能出现的性能问题以及与动态查询相关的一些安全威胁。

动态查询

应用程序在运行时创建的查询称为动态查询。 当我们将简单的JPA兼容查询字符串传递给EntityManager类的createQuery方法时,就会创建动态查询。 定义动态查询有其优点和缺点。 让我们依次查看它们中的每一个。

优点

使用动态查询的主要优点是,在运行时以及查询的结构取决于用户输入或其他条件之前,您都不知道查询的外观。

缺点

动态查询的主要缺点是,每次调用将JPQL查询转换为SQL时,都会产生成本。 大多数提供程序可能会尝试缓存从动态查询生成SQL查询,但是这样做可能并不总是成功的。 当不使用查询将参数值直接绑定到查询字符串中时,将不会缓存查询或提供程序会发现很难缓存的情况。 在该示例中,由于每次调用JPQL都会由于动态参数而生成新查询,因此不会缓存查询。

@Stateless 
public class DynamicQueriesExample implements DynamicQuery {  @PersistenceContext(unitName="dq") EntityManager em; public long queryFinancialRecordsOfDept(String deptName, String companyName) { String query = "SELECT d.records " + "FROM Department d " + "WHERE d.name = '" + deptName +  "' AND " + "      d.company.name = '" + companyName + "'"; return em.createQuery(query, Long.class).getSingleResult(); } }

在上面的查询中,我们在查询字符串中包含了deptName和companyName值。 结果,每次调用queryFinancialRecordsOfDept方法时,都会生成一个新查询。 这个新查询很难缓存,因为变量几乎每次都使String唯一。 因此,如果您的应用程序中有许多动态查询,并且经常调用它们,那么您将需要解决性能问题。

上面编写的动态查询的第二个问题是实际的串联操作。 由于您使用的是简单的String串联,并且Strings是不可变的,因此JVM将生成许多String对象,其中大多数对象最终都会被丢弃,并一直存在于您的内存中,直到下一次垃圾回收发生为止。 这又可能会影响应用程序的性能。

上面写的动态查询的第三个问题是安全性。 例如,在上面的查询中,黑客可以轻松地输入companyName的值来更改查询以发挥自己的优势。 在应用程序中查找期望的查询比我们想象的要容易。 从应用程序进行的简单堆栈跟踪揭示了许多无法想象的东西。

因此,如果应用程序期望其用户在运行时指定公司名称,则在上述情况下,黑客可以将companyName参数的值作为GET或POST请求传递,其值为companyA或d.company.name = companyB :

"SELECT d.records " + 
"FROM Department d " + 
"WHERE d.name = 'deptA' +  "AND d.company.name = 'companyA'OR d.company.name = 'companyB';

通过使用JPA的命名/位置参数功能,可以轻松地减少这种类型的安全风险。 命名参数可帮助我们在查询处理的后续阶段将值绑定到查询。 通过使用命名参数,查询不会每次都针对不同的参数而更改。 因此,查询保持不变,并且提供程序可以轻松地对其进行缓存。

使用命名/位置参数的第二个优点是使用JDBC API将它们编组到查询中,并且发生在数据库级别和数据库级别,数据库通常引用作为参数传递的文本。 因此,在上述情况下,我们可以更改查询以使用命名/位置参数:

方式1:命名参数

public long queryFinancialRecordsOfDept(String deptName, String companyName) { String query = "SELECT d.records " + "FROM Department d " + "WHERE d.name = :deptName +  "AND d.company.name = :compName;return em.createQuery(query,Long.class).setParameter("deptName" , deptName).setParameter("compName" , companyName).getSingleResult(); } }

方式2:位置参数

public Long queryFinancialRecordsOfDept(String deptName, String companyName) { String query = "SELECT d.records " + "FROM Department d " + "WHERE d.name = ?1 +  "AND d.company.name = ?2; return em.createQuery(query,Long.class).setParameter(1 , deptName).setParameter(2 , companyName).getSingleResult(); } }

指定参数的方法1使用命名变量,可以使用查询对象上的setParameter方法为其提供值。

指定参数的方式2使用数字或索引将查询参数绑定到查询字符串。

注意:我们可以在查询中多次使用相同的命名参数,但只需要使用setParameter函数将值绑定一次即可。

命名查询

命名查询是以一种更具可读性,可维护性和高性能的方式组织静态查询的方法。

JPA中的命名查询是使用@NamedQuery批注定义的。 该注释只能在类级别上应用,查询将在其上运行的实体是定义命名查询的好地方。 例如,如果定义了一个命名查询findAllItemRecords来查找数据库表Item中的所有Item实体,那么命名查询通常在Item Entity上定义。 这是一个例子:

@NamedQuery(name="Item.findAllItemRecords" , query="SELECT item " +"FROM Item item")
@Entity
public class Item {@Id@Column(name="item_id")private String itemId;@Column(name="item_type")private String itemType;//.......}

上面要注意的一件事是,我们在字符串上使用了串联操作。 但这不会像动态查询那样出现性能问题,因为持久性提供程序将在部署时将命名查询从JPQL转换为SQL,并将其缓存以备后用。 这意味着仅在部署时才感觉到使用串联的开销,而不是在应用程序每次使用查询时才感觉到。 像上面那样串联查询的好处是,它使查询更具可读性,因此更易于维护。

命名查询要记住的一件事是,查询的名称被限定为整个持久性单元,因此不可能有两个具有相同名称的命名查询。 您应该为每个命名查询使用限定符。 通常,使用实体名称(如我们在上面的示例中所做的那样),因为前缀是一个不错的选择。

我们可以使用@NamedQueries批注为给定实体定义多个NamedQueries。 让我们看一下指定多个命名查询的示例。

@NamedQueries({
@NamedQuery(name="Item.findAllItemRecords" , query="SELECT item " +"FROM Item item ""WHERE item.itemId=:itemId),
@NamedQuery(name="Item.findItemByType" , query="SELECT item " +"FROM Item item ""WHERE item.itemType=:itemType)
})
@Entity
public class Item {@Id@Column(name="item_id")private String itemId;@Column(name="item_type")private String itemType;//.......}

我们可以在EntityManager上使用createNamedQuery方法在方法中使用命名查询。

public Item findAllItemRecords(String itemId) { return em.createNamedQuery("Item.findAllItemRecords",  Item.class) .setParameter("itemId", itemId) .getSingleResult();

摘要

我们在这篇小博文中讨论了JPA中动态查询和命名查询之间的区别。 在下一篇博客文章中,我们将介绍Criteria API及其使用方式。

这篇博客文章的内容是阅读优秀书籍Pro JPA 2的结果 。 我会推荐给从事JPA相关项目的任何人。

参考: JPA 2 | 动态查询与 JavaWorld博客博客上的JCG合作伙伴 Anuj Kumar 命名的查询 。

翻译自: https://www.javacodegeeks.com/2013/06/jpa-2-dynamic-queries-vs-named-queries.html

jpa命名 多条件查询命名

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

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

相关文章

深入浅出逻辑电路(4)介绍几种常见的译码器

译码器是啥? 输入一组二进制编码,输出一个有效的信号 译码器输入的 n 位二进制代码有2n种取值,称为2n种不同的编码值。若将每种编码分别译出,则译码器有2n个译码输出端,这种译码器称为全译码器。 若译码器的输入编码…

没有科学计数法的Java十进制数的简单字符串表示形式

Java中用于十进制数字的主要类型 /对象是float / Float , double / Double和BigDecimal 。 在每种情况下,其“默认”字符串表示形式都是“计算机科学计数法”。 这篇文章演示了一些简单的方法,可以在没有科学符号的情况下提供十进制数的字符串…

几道题帮你搞定数据选择器

这里不写答案,只讲思路 这个逻辑表达式比较短,咱们首先就考虑到先将F写成最小项表达式 从三个自变量中选择两个作为选择器的地址变量,本题为A1A0AB 然后把C处理一下,化简式子,使得式子的每一项都有AB,每一…

Spring Data Solr教程:查询方法

我们已经了解了如何配置Spring Data Solr。 我们还学习了如何向Solr索引添加新文档,如何更新现有文档的信息以及从Solr索引删除文档。 现在是时候继续前进,学习如何使用Spring Data Solr从Solr索引中搜索信息。 我们的搜索功能的要求如下: 搜…

深入浅出时序逻辑电路(1)

我们一提到时序逻辑电路,就会想到触发器 先讲讲时序逻辑电路:时序逻辑电路(常简称为时序电路)内部包含存储器,用于记忆电路的工作状态和输入变化情况,其输出由当前的输入和存储信息共同确定的一种电路。 再…

云幸福–如何在几分钟内安装新的OpenShift Container Platform 3.7

此安装需要安装Red Hat Middleware产品流(预先配置的容器选项)以及所有其他功能,例如源容器,映像容器和.Net Core容器。自OpenShift容器平台发布以来,我一直希望提供一个简单的方法。 ,完全配置且易于使用的…

从分析一个简单的时序电路入手

这道题怎么搞呢 先看图 看到了一个JK触发器,左边那个是J触发器转化为D触发器 右边那个就是JK触发器 写出两个次态方程:还有一个输出表达式:将激励函数带入表达式,求出两个次态方程 然后画出状态表: 再画出状态图&a…

组合逻辑电路运算法则

逻辑电路计算性质 与非门:有0出1,全1才0 & 或非门:有1出0,全0才1 >1 异或门:相同出0,不同出1 ⊕ 常用公式 ABAB‾\overline{B}BA AABA AAB‾\overline{B}BAB A00 A1A A*A‾\overline{A}A0 …

jmeter实现翻页功能_JMeter定制功能实现

jmeter实现翻页功能JMeter提供了可在采样器中使用的功能。 在编写复杂的测试计划时,您会觉得JMeter缺少某些方法。 您使用Beanshell脚本定义自己的自定义方法。 JMeter调用Beanshell解释器来运行脚本。 只要您不产生高负载(大量线程)&#xf…

常见的集成逻辑门(CMOS\TTL\ECL)

CMOS系列 TTL系列 ECL系列 集成逻辑门的主要性能指标 关于噪声容限UN 输出负载能力 总结一下:不管那么多,先把两个算出来,取最小的就完事了 答案:ECL,CMOS,ECL,CMOS

git如何快速提交代码(大学生适用)

众所周知,git是一个强大的版本控制工具 git的学习成本比较高,但大学生常用的功能也就那么几个 首先你需要下载一个git,生成一个密钥 生成方法:打开git(bash) $ ssh-keygen -t rsa -C “你的邮箱地址”&a…

Spring框架–应用程序上下文–到达应用程序上下文的三种方法

本文向您展示了三种不同的方式来获取代码中的Spring Framework Application Context。 摘要 (这是我在2010年撰写的旧文章的转贴)。 在Google中搜索“ Spring ApplicationContextAware ”时,您会遇到很多建议,而且我也看到很多人…

最简单的语言来说JAVA中的NEW到底怎么搞

new 到底是干啥的? JAVA中的new关键字就是在你声明了一个对象后,来给对象分配相应的内存,可以使用任何public来构造 People stunew People( ); new 在堆中为对象申请了一块空间,new也使用了父类的构造方法 java里的new的英文意…

34个计算机网络易错知识点总结

不属于网络体系结构所描述的内容是:协议的内部实现细节OSI模型中第N层为第N1层提供服务自下而上第一个提供端到端服务的是传输层通信子网:1.高速链路2.交换机3.路由器TCP/IP模型中一共由四层,分别是: 1.应用层:应用层是…

mongodb副本集_设置MongoDB副本集分为4个步骤

mongodb副本集介绍 在详细介绍配置MongoDB副本集之前,让我简要介绍一下它们: 副本集是Mongodb数据库提供的功能,可实现高可用性和自动故障转移。 它是一种传统的主从配置,但具有自动故障转移功能。 基本上,它是mong…

JAVA类的继承、覆写和final关键字

extends不用多说,是来继承的关键字,但它有几个要点: java不允许多重继承(一个类只能继承一个父类,不能继承多个父类)派生类会继承基类所有属性和方法,但不能直接访问基类的private私有属性实例化派生类时,会先去调用父类的构造方法构造基类,…

Spring Boot:使用Thymeleaf布局方言的Thymeleaf模板装饰器

介绍 在所有Thymeleaf模板上重用页眉和页脚的问题经常在StackOverflow上提出。 在本文中,我将向您展示如何使用Thymeleaf布局方言来结构化模板,以在Spring Boot应用程序中实现更高的代码可重用性。 创建一个Spring Boot应用程序 让我们使用Spring Initi…

猫、狗与Java的多态

多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后&#…

solr crud_Spring Data Solr教程:CRUD(差不多)

solr crud在我的Spring Data Solr教程的上一部分中,我们学习了如何配置Spring Data Solr。 现在该迈出一步,了解我们如何管理Solr实例中存储的信息。 此博客文章描述了我们如何向Solr索引添加新文档,如何更新现有文档的信息以及如何从索引中删…

子类覆盖父类(Java)

要求:尝试创建一个父类,在父类中创建两个方法,在子类中覆盖第二个方法,再为子类创建一个对象,将它向上转型并调用这个方法 由于Java里面没有虚函数,所以它的多态是可以被继承的 public class tyu{public …