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 手动预编译

jpa 手动预编译_编译时检查JPA查询相关推荐

  1. 编译时检查JPA查询

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

  2. opengl2 vtk 编译_编译和使用VTK时值得注意的点(待续)

    最近的一个项目中需要使用VTK,于是开始了VTK的漫漫编译之路.长篇大论的编译步骤网上数不胜数,在这里不再细说,可自行google.这里主要说一些在编译过程中需要注意的地方,以免走歪路. 1.使用cm ...

  3. python文件编译_编译Python文件

    编译Python文件 一.编译Python文件 为了提高加载模块的速度,强调强调强调:提高的是加载速度而绝非运行速度.python解释器会在__pycache__目录中下缓存每个模块编译后的版本,格式 ...

  4. aosp 为什么某些目录没有编译_编译Android AOSP代码

    下载完了源代码,终于到了编译的阶段了.这个阶段远比你想象的简单,一个make命令就可以完成源代码的编译了.参照下面的教程你就可以编译出适用于Android源代码树上的所有分支,包括master.基本的 ...

  5. mysql 5.6.30 编译_编译安装mysql 5.6.30

    一:安装系统环境: php-gd policycoreutils ppl telnet t1lib t1lib* wget zlib-devel 2:编译过程: cmake . -DCMAKE_INS ...

  6. 大数据之-Hadoop源码编译_编译hadoop源码前_需要准备的软件_以及编译步骤---大数据之hadoop工作笔记0045

    编译源码,首先要准备一台Centos可以联网的虚拟机,一定要可以连接外网 然后准备上面的这些软件. 可以看到软件都在上面这个目录下. 首先是安装jdk,然后配置JAVA_HOME

  7. opencv python 编译_编译opencv python

    1, 下载并且安装python2.7 + numpy 2,运行cmakegui打开opencv.应该要显示如下信息: Python 2: Interpreter: C:/Python27/python ...

  8. jpa transaction 回滚_我遇到的JPA中事务回滚的问题

    在最近的项目中,做的是解析XML文件,解析过程中会有异常,比如:XML文件中节点的数据和与之对应的数据库的字段中数据的类型不匹配:XML中数据长度超过数据库定义的长度:有数据了的重复插入问题:读取节点 ...

  9. spring jpa mysql集群_微框架:Springboot+Jpa+mysql零基础上手班

    [课前科普百科] 企业的很多技术都是保密的,尤其是实战项目和新兴技术.Springboot是目前互联网薪的技术.Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spr ...

最新文章

  1. 巧用CSS的alpha滤镜
  2. Leetcode 62. Unique Paths
  3. linux debain systemd 开机启动 nodejs 兼容原initd启动 forever 开机自启
  4. python学习笔记(四)字典(dict)
  5. 【字幕制作】生肉资源的字幕问题解决经验分享 入门科普/一键机翻/在线识别/内嵌封装
  6. matlab编写LDA,lda算法matlab实现
  7. 如何给计算机安装驱动程序,电脑系统怎么安装驱动程序
  8. 地图比例尺与空间分辨率之间的关系_航高、分辨率与比例尺的关系
  9. mac mini u盘安装系统_系统安装丨如何制作U盘启动盘?
  10. 趣图:各种程序员的键盘热力图
  11. 微信小程序-从相册获取图片,视频 使用相机拍照,录像上传+服务器(nodejs版)接收
  12. Camtasia Studio 录制视频保存为camrec格式后快速导出为AVI格式
  13. Saber 2016安装过程分享
  14. 查看ubuntu服务器防火墙配置文件,Ubuntu Server服务器防火墙ufw开启及配置方法 | 坐倚北风...
  15. 云平台学习笔记(三)-实践
  16. 二十四节气之大暑时节常识介绍
  17. **公司软件开发人员绩效评价标准(zt)
  18. 元器件封装标准IPC-7351
  19. 五、Jenkins系列_使用scp命令进行远程文件复制遇到的坑
  20. 【AirServer for Mac】将iOS设备投屏到Mac,免激活版分享

热门文章

  1. nssl1218-TRAVEL【SPFA】
  2. 行列式、LGV、矩阵树学习笔记
  3. 【dfs】数独游戏(ybtoj dfs-1-2)
  4. Full_of_Boys训练6总结
  5. codeforces 935E Fafa and Ancient Mathematics 语法树、动态规划
  6. 深入Java类型信息:RTTI和反射
  7. Maven精选系列--过滤不同环境配置文件
  8. Shell入门(三)之字符串
  9. 别在被骗了!!!!!!
  10. JS生成x到y的随机数