jpa 手动预编译_编译时检查JPA查询

jpa 手动预编译

JPA提供了几种查询数据的方法。 可以根据各种标准(例如,使用的语言(SQL与JPQL)或查询是静态的(编译时间)还是动态的(执行时间))对此类替代方案进行分类。

静态查询是使用@Entity类定义本身中的注释@NamedQuery ( javax.persistence.NamedQuery )和@NamedQueries ( javax.persistence.NamedQueries )定义的:

@NamedQuery(name="findAllCustomersWithName",query="SELECT c FROM Customer c WHERE c.name LIKE :custName")

另一方面, EntityManager提供了分别接受JPQL或SQL查询的createQuery(…)createNativeQuery(…)方法。

因此,可以在编译或执行时定义查询。

注意 :建议始终使用Query中的 setParameter(…)方法来使用参数化查询,以避免SQL注入漏洞。)

标准API

但是,JPA提供了另一种查询对象的方法: Criteria API 。 确实,切换到JPA的动机之一是处理对象而不是SQL方言,不是吗?

让我们看一个示例代码。

实体定义:

@Entity
public class User {@Idprivate Integer userId;@Basic@Column(length=15, nullable=false)private String name;@Basic@Column(length=64, nullable=false)private String userDigestedPasswd;@Basic@Column(length=50, nullable=true)private String email;@Basic@Column(nullable=false)public Integer privilegeLevel;@Basic@Column(nullable=false)private Boolean active;
}

让我们查询数据库并检查结果(使用JUnit):

public class UserTest {@Testpublic void testUserCriteria(){
EntityManagerFactory emf = null;
EntityManager em = null;
try {emf = Persistence.createEntityManagerFactory("criteria");em = emf.createEntityManager();final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<User> q = cb.createQuery(User.class);final Root<User> users = q.from(User.class);final Predicate condition = cb.equal(users.get("privilegeLevel"), 5);q.select(users).where(condition).orderBy(cb.asc(users.get("userId")));em.getTransaction().begin();List<User> result = em.createQuery(q).getResultList();em.getTransaction().commit();assertNotNull(result);assertEquals(2, result.size());assertEquals(1, (int)result.get(0).getUserId());assertEquals("Pepe", result.get(0).getName());assertEquals(3, (int)result.get(1).getUserId());assertEquals("Dolores", result.get(1).getName());} catch (Exception e) {fail("Unexpected Exception " + e.getMessage());
} finally {if (em != null)em.close();if (emf != null)emf.close();
}
}
}

以下几行显示查询的创建:

final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<User> q = cb.createQuery(User.class);final Root<User> users = q.from(User.class);final Predicate condition = cb.equal(users.get("privilegeLevel);q.select(users).where(condition).orderBy(cb.asc(users.get("userId

首先,从EntityManager获得CriteriaBuilder 。 然后,获取一个CriteriaQuery实例,将该类设置为保存结果。 在我们的例子中, User.class

final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<User> q = cb.createQuery(User.class);

接下来,必须设置要对其运行查询的实体:

final Root<User> users = q.from(User.class);

现在是时候设置查询匹配条件了。 在示例代码中,条件只是属性privilegeLevel等于5:

final Predicate condition = cb.equal(users.get("privilegeLevel"), 5);

最后,构建查询以在Root上添加条件。 也可以设置分组和排序选项(即,对userId设置升序):

q.select(users).where(condition).orderBy(cb.asc(users.get(“userId”)));

请查看CriteriaBuilder中的不同选项。 可以在CriteriaQuery中找到分组和排序选项。

使用元模型进行编译时检查

请注意,我们刚刚构建的查询需要跟踪对象属性名称。 例如,要构建查询,将使用属性privilegeLevel的名称。 但是,如果稍后更改属性名称,则代码将编译并且仅在运行时失败:

final CriteriaQuery<User> q = cb.createQuery(User.class);final Root<User> users = q.from(User.class);final Predicate condition = cb.equal(users.get("privilegeLevel"), 5);q.select(users).where(condition).orderBy(cb.asc(users.get("userId")));

那不好

幸运的是,使用元模型,我们将能够构建编译时检查的查询。 可以在The Java EE6 Tutorial中找到简短的介绍。

使用元模型,代码将引用对象的SingularAttribute,而不是使用包含对象属性名称的String。 因此,如果稍后更改对象属性,则编译器将为我们标记该属性。

首先,必须创建对应的元模型类( EntityType )。 尽管可以通过多种方式实现,但对于openJPA实现,最简单的方法可能是添加一个openJPA构建标记 : -Aopenjpa.metamodel = true

因此,我们创建了User_类,它是User的对应元模型类:

* Generated by OpenJPA MetaModel Generator Tool. **/
package com.wordpress.tododev.criteria.entities;
import javax.persistence.metamodel.SingularAttribute;
@javax.persistence.metamodel.StaticMetamodel
(value=com.wordpress.tododev.criteria.entities.User.class)
@javax.annotation.Generated
(value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Mon Mar 04 16:47:46 CET 2013")
public class User_ {public static volatile SingularAttribute<User,Boolean> active;public static volatile SingularAttribute<User,String> email;public static volatile SingularAttribute<User,String> name;public static volatile SingularAttribute<User,Integer> privilegeLevel;public static volatile SingularAttribute<User,String> userDigestedPasswd;public static volatile SingularAttribute<User,Integer> userId;
}

如果将此类添加到代码库中,则以后对User类的任何更改都不会引起注意。 而且,将自动生成的项目添加到代码版本控制系统中不是一个好主意。

使用antmaven或类似工具,可以添加目标以创建元模型类。 在更改JPA实体后,应执行该目标。

也可以使用IDE。 例如,对于使用Eclipse的,只需要已经提到编译标志添加属性- > Java的反编译>注解处理器和的lib(JAR)包含所选择的JPA实现第厂路注释处理器的注释处理器(可能导致自动模式下的编译问题,前提是必须在使用它的代码之前编译元模型类)。

让我们向套件添加另一个测试。 这个不会提供包含属性名称的String,而是使用metamodel类:

@Testpublic void testUserCriteriaMetaModel(){EntityManagerFactory emf = null;EntityManager em = null;try {emf = Persistence.createEntityManagerFactory("criteria");em = emf.createEntityManager();final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<User> q = cb.createQuery(User.class);final Metamodel m = em.getMetamodel();final Root<User> user = q.from(m.entity(User.class));final Predicate condition = cb.equal(user.get(User_.privilegeLevel), 5);q.select(user).where(condition).orderBy(cb.asc(user.get(User_.userId)));em.getTransaction().begin();List<User> result = em.createQuery(q).getResultList();em.getTransaction().commit();assertNotNull(result);assertEquals(2, result.size());assertEquals(1, (int)result.get(0).getUserId());assertEquals("Pepe", result.get(0).getName());assertEquals(3, (int)result.get(1).getUserId());assertEquals("Dolores", result.get(1).getName());
} catch (Exception e) {fail("Unexpected Exception " + e.getMessage());} finally {if (em != null)em.close();if (emf != null)emf.close();}}

更相关的更改是user.get(User_.privilegeLevel)而不是users.get(“ privilegeLevel”)  user.get(User_.userId)而不是   users.get(“ userId”)。

  • 从GitHub下载源代码。

翻译自: https://www.javacodegeeks.com/2014/08/compile-time-checking-jpa-queries.html

jpa 手动预编译

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

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

相关文章

多层陶瓷电容器用处_【科普贴】多层陶瓷电容器的制造工序,你知道吗?

本文将向大家介绍多层陶瓷电容器的结构及制造工序。多层陶瓷电容器的基本结构电容器用于储存电荷&#xff0c;其最基本结构如图1所示&#xff0c;在2块电极板中间夹着介电体。图1. 电容器的基本结构电容器的性能指标也取决于能够储存电荷的多少。多层陶瓷电容器为了能够储存更多…

使用ORM提取数据很容易! 是吗?

介绍 几乎任何系统都以某种方式与外部数据存储一起运行。 在大多数情况下&#xff0c;它是一个关系数据库&#xff0c;并且数据获取通常委托给某些ORM实现。 ORM涵盖了很多例程&#xff0c;并带来了一些新的抽象作为回报。 Martin Fowler写了一篇有关ORM的有趣文章 &#xff0…

分段式多级离心泵_离心泵与多级离心泵工作原理

离心泵工作原理&#xff1a;离心泵工作时&#xff0c;液体注满泵壳&#xff0c;叶轮高速旋转&#xff0c;液体在离心力作用下产生高速度&#xff0c;高速液体经过逐渐扩大的泵壳通道&#xff0c;动压头转变为静压头。性能特点&#xff1a;高效节能&#xff1a;泵有高效的水力形…

java8 javafx_JavaFX技巧8:美丽深层

java8 javafx如果您正在开发JavaFX的UI框架&#xff0c;请养成一种习惯&#xff0c;始终将自定义控件拆分为控件类和外观类。 来自Swing自己&#xff0c;这对我来说并不明显。 Swing还使用MVC概念&#xff0c;并将实际的组件呈现委托给UI委托&#xff0c;但是扩展Swing的人们大…

牛客网数据开发题库_数据库刷题—牛客网(21-30)

21.查找所有员工自入职以来的薪水涨幅情况&#xff0c;给出员工编号emp_no以及其对应的薪水涨幅growth&#xff0c;并按照growth进行升序CREATE TABLE employees ( emp_no int(11) NOT NULL, birth_date date NOT NULL, first_name varchar(14) NOT NULL, last_name varchar(16…

弹性堆栈介绍

当您运行对公司至关重要的软件时&#xff0c;您将无法获得仅用于分析一段时间前发生的事情的日志&#xff0c;让客户端告诉您您的应用程序已损坏&#xff0c;而您甚至不知道发生了什么是真实的问题。 解决该问题的方法之一是使用监视和日志记录。 大多数应用程序都将具有日志记…

access统计没有选课的人数_当代大学生发愁求职就业,更发愁“选课”,自主选课变成了负担...

当代大学生除了求职就业&#xff0c;最发愁的就是“选课”。不得不说&#xff0c;随着科技的发展&#xff0c;各行各业都发生了翻天覆地的变化。而在大学里的选课&#xff0c;也因此有了巨大的改变。过去&#xff0c;大学生上课&#xff0c;其实课程都是被安排好的&#xff0c;…

产线数字化软件源码_品质笔记⑥丨卢宇聪:把握数字化趋势,坚定创新发展道路...

6天5夜&#xff0c;跨越3座城市&#xff0c;深度走访7家企业&#xff0c;对话多位企业家……这是一趟开阔视野之旅。我接触了很多之前极少有机会接触的企业&#xff0c;比如做光缆的法尔胜泓晟集团、做节能装备的双良集团、做密封件的天生密封件有限公司等。我以前经常接触的是…

es 安装kopf_Elasticsearch-kopf导览

es 安装kopf当我需要一个插件来显示Elasticsearch的集群状态时&#xff0c;或者需要深入了解通常为经典插件elasticsearch-head所达到的索引时。 由于有很多建议&#xff0c;而且似乎是非官方的继任者&#xff0c;所以我最近更详细地研究了elasticsearch-kopf 。 我喜欢它。 我…

会导致小程序onhide码 手机息屏_小程序onshow事件

问题描述onShow 事件在小程序里面非常重要&#xff0c;场景之多&#xff0c;导致处理起来很复杂。很多业务场景依赖与onShow与onHide事件。比如分享给他人&#xff0c;在群里PK等等。息屏&#xff0c;新页面返回、Home键操作&#xff0c;也会触发onShow事件。以下是官网的说明&…

Spring@主要注释

介绍&#xff1a; 当存在多个相同类型的bean时&#xff0c;使用Spring Primary批注为标记的bean提供更高的优先级。 默认情况下&#xff0c;Spring按类型自动连线。 因此&#xff0c;当Spring尝试自动装配并且有多个相同类型的bean时&#xff0c;我们将获得NoUniqueBeanDefini…

python帮助文档快捷键_Pycharm快捷键手册

AltEnter 自动添加包Ctrlt SVN更新Ctrlk SVN提交Ctrl / 注释(取消注释)选择的行CtrlShiftF 高级查找CtrlEnter 补全Shift Enter 开始新行TAB ShiftTAB 缩进/取消缩进所选择的行Ctrl Alt I 自动缩进行Ctrl Y 删除当前插入符所在的行Ctrl D 复制当前行、或者选择的块Ctrl …

arm 交叉编译找不到so_搭建交叉编译环境并验证

1. 搭建编译环境并验证1.1 实验目的 掌握嵌入式开发环境、交叉编译器的搭建、安装和配置方法 熟悉Linux应用程序的编译、调试方法&#xff0c;能够验证X86平台和ARM平台的差异1.2 实验内容 交叉编译器环境搭建 编写一个典型的Linux应用程序 使用GDB调试Linux程序(PC平台) 用Mak…

雷达的工作原理示意图_电磁阀的构成和工作原理示意图

电磁阀符号的含义&#xff1a;电磁阀符号由方框、箭头、“T”和字符构成。电磁阀图形符号的含义一般如下&#xff1a;1、用方框表示阀的工作位置&#xff0c;每个方块表示电磁阀的一种工作位置&#xff0c;即“位”。有几个方框就表示有几“位”&#xff0c;如二位三通表示有两…

JDK 14 Rampdown:内部版本27

马克 雷因霍尔德&#xff08; Mark Reinhold&#xff09;最近的帖子“ JDK 14现在处于Rampdown第一阶段 ”宣布“我们现在处于Rampdown第一阶段”&#xff0c;并且“整体功能已冻结”。 JDK 14 Early Access Build &#xff03;27&#xff08;2019/12/12&#xff09;是一个繁重…

从金蝶k3到金税盘_经典全套金蝶K3操作流程大全

—结帐—期末结帐注意点&#xff1a;不能结帐的原因&#xff1a;(1)有未过帐的凭证(2)无权限(3)其他子系统未结帐(4)与其他用户冲突八、套打1、套打格式凭证&#xff1a;*上海TR101记帐凭证上海TR102收款凭证 纸张大小&#xff1a;自定义大小上海TR103付款凭证 宽度&#xff1a…

sqlserver拼接字符串换行_1.3【Python】第三章 字符串

人工智能入门与实战第一季&#xff1a;python基础语法字符串是比较常见的数据类型&#xff0c;在第一章中我们最早接触的数据类型就是字符串&#xff1a;"hello world"&#xff0c;字符串可以用单引号’‘或双引号""来表示代码示例&#xff1a;name "…

jsf按钮响应事件_如何从JSF获取JSON响应?

jsf按钮响应事件许多JavaScript小部件都希望使用JSON格式的数据和选项。 如今&#xff0c;选择一个很酷的小部件并将其包装在一个复合组件中确实很容易。 但是第一个问题是如何发送AJAX请求并以正确的JSON格式接收响应。 JSF用户经常会提出这个问题 。 您需要的只是一个XHTML f…

mot数据集_谈谈ReID与MOT的关系

1.ReID与MOT的联系在MOT任务中&#xff0c;一般常用的特征模型有运动模型和表观模型&#xff0c;其中表观模型以行人重识别(ReID)类算法为主流。Re-ID任务主要解决的是跨摄像头场景下行人的识别与检索&#xff0c;其中存在给定了身份的图片序列query&#xff0c;需要为不同摄像…

jClarity:在Azure上升级到Java

在互联世界公共基础结构的新时代&#xff0c;最大和最重要的两个方面是Java和OpenJDK的诞生和兴起。 因此&#xff0c;许多公司将时间和资源投入到构建最先进的技术上&#xff0c;以确保整个行业在未来几年内在AdoptOpenJDK上拥有丰富的质量&#xff0c;而且免费的OpenJDK二进制…