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类的任何更改都不会引起注意。 而且,将自动生成的项目添加到代码版本控制系统中不是一个好主意。
使用ant , maven或类似工具,可以添加目标以创建元模型类。 在更改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 手动预编译
jpa 手动预编译_编译时检查JPA查询相关推荐
- 编译时检查JPA查询
JPA提供了几种查询数据的方法. 可以根据各种标准(例如,所使用的语言(SQL与JPQL)或查询是静态的(编译时间)还是动态的(执行时间))对此类替代方案进行分类. 静态查询是使用@Entity类定义 ...
- opengl2 vtk 编译_编译和使用VTK时值得注意的点(待续)
最近的一个项目中需要使用VTK,于是开始了VTK的漫漫编译之路.长篇大论的编译步骤网上数不胜数,在这里不再细说,可自行google.这里主要说一些在编译过程中需要注意的地方,以免走歪路. 1.使用cm ...
- python文件编译_编译Python文件
编译Python文件 一.编译Python文件 为了提高加载模块的速度,强调强调强调:提高的是加载速度而绝非运行速度.python解释器会在__pycache__目录中下缓存每个模块编译后的版本,格式 ...
- aosp 为什么某些目录没有编译_编译Android AOSP代码
下载完了源代码,终于到了编译的阶段了.这个阶段远比你想象的简单,一个make命令就可以完成源代码的编译了.参照下面的教程你就可以编译出适用于Android源代码树上的所有分支,包括master.基本的 ...
- mysql 5.6.30 编译_编译安装mysql 5.6.30
一:安装系统环境: php-gd policycoreutils ppl telnet t1lib t1lib* wget zlib-devel 2:编译过程: cmake . -DCMAKE_INS ...
- 大数据之-Hadoop源码编译_编译hadoop源码前_需要准备的软件_以及编译步骤---大数据之hadoop工作笔记0045
编译源码,首先要准备一台Centos可以联网的虚拟机,一定要可以连接外网 然后准备上面的这些软件. 可以看到软件都在上面这个目录下. 首先是安装jdk,然后配置JAVA_HOME
- opencv python 编译_编译opencv python
1, 下载并且安装python2.7 + numpy 2,运行cmakegui打开opencv.应该要显示如下信息: Python 2: Interpreter: C:/Python27/python ...
- jpa transaction 回滚_我遇到的JPA中事务回滚的问题
在最近的项目中,做的是解析XML文件,解析过程中会有异常,比如:XML文件中节点的数据和与之对应的数据库的字段中数据的类型不匹配:XML中数据长度超过数据库定义的长度:有数据了的重复插入问题:读取节点 ...
- spring jpa mysql集群_微框架:Springboot+Jpa+mysql零基础上手班
[课前科普百科] 企业的很多技术都是保密的,尤其是实战项目和新兴技术.Springboot是目前互联网薪的技术.Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spr ...
最新文章
- 巧用CSS的alpha滤镜
- Leetcode 62. Unique Paths
- linux debain systemd 开机启动 nodejs 兼容原initd启动 forever 开机自启
- python学习笔记(四)字典(dict)
- 【字幕制作】生肉资源的字幕问题解决经验分享 入门科普/一键机翻/在线识别/内嵌封装
- matlab编写LDA,lda算法matlab实现
- 如何给计算机安装驱动程序,电脑系统怎么安装驱动程序
- 地图比例尺与空间分辨率之间的关系_航高、分辨率与比例尺的关系
- mac mini u盘安装系统_系统安装丨如何制作U盘启动盘?
- 趣图:各种程序员的键盘热力图
- 微信小程序-从相册获取图片,视频 使用相机拍照,录像上传+服务器(nodejs版)接收
- Camtasia Studio 录制视频保存为camrec格式后快速导出为AVI格式
- Saber 2016安装过程分享
- 查看ubuntu服务器防火墙配置文件,Ubuntu Server服务器防火墙ufw开启及配置方法 | 坐倚北风...
- 云平台学习笔记(三)-实践
- 二十四节气之大暑时节常识介绍
- **公司软件开发人员绩效评价标准(zt)
- 元器件封装标准IPC-7351
- 五、Jenkins系列_使用scp命令进行远程文件复制遇到的坑
- 【AirServer for Mac】将iOS设备投屏到Mac,免激活版分享