我们经常会碰上某个字段是集合元素(List,Set)的情况,并且我们要过滤出集合中包含某个或某些元素的数据。
譬如一个类User

 /*** 检索人*/private Long userId;/*** 省、直辖市集合*/@ElementCollection@CollectionTableprivate List<String> provinces;/*** 市、区集合*/@ElementCollection@CollectionTableprivate List<String> cities;/*** 行业集合*/@ElementCollection@CollectionTableprivate List<Integer> vocations;

包含一个String型的集合,我们希望能查询出province="1"或者"2"的User集合。
倘若使用Hql或者原生sql是比较简单的,但是使用Criteria查询就不那么简单了,尤其是当User中包含多个集合元素,并且查询条件不确定时。
Jpa中Criteria用来构建复杂查询,之前我的文章中(http://blog.csdn.net/tianyaleixiaowu/article/details/72876732)已经讲过了如何构建动态条件查询,里面就有如何实现查询集合元素中是否包含某元素的功能。
重点看一下那篇文章中的SimpleExpression.java,里面的case IS_MEMBER,调用了CriteriaBuilder的isMember方法,该方法就能查询出你的集合中是否包含某个元素。
请注意,我定义User类时,注解写的是:@ElementCollection,映射的是基本类型不是一个javaBean类,所以无法使用表关联的写法如user.address.id=XXX,这样的hibernate表关联写法。
那么就需要使用isMember这样的写法(注意:需要导入上面提到的那篇文章的几个类,才能用下面的写法):

        Criteria<PtSearchCondition> criteria = new Criteria<>();criteria.add(Restrictions.hasMembers("provinces", "110000", "120000"));Page page = userRepository.findAll(criteria, new PageRequest(0, 10));return page.getContent();

有个地方需要说明一下,@ElementCollection这个注解代表该属性是一个集合属性,它和one-to-many类似,但不是同一个东西,one-to-many注解的另一方也要是一个表,不能只是一个普通的基本类型的集合。
如果你的@ElementCollection注解的集合对象也是一个JavaBean,不是String或者Integer时,譬如User有多个Address,Set《Address》 addressSet,那么Address类需要加@Embeddable注解,否则报错。@Embeddable代表是一个嵌入式的对象,不是一个表映射对象。如果你用的是one-to-many,那么Address就需要加上@Entity,代表需要映射到数据库表。
下面还看查询的问题:
如果你的属性是一个对象的集合,并且是@ElementCollection注解的,那么如何查询呢?
很简单,同样还是使用

 Criteria<PtSearchCondition> criteria = new Criteria<>();criteria.add(Restrictions.hasMembers("address.name", "北京"));Page page = userRepository.findAll(criteria, new PageRequest(0, 10));

在我的SimpleExpression.java中,有这样一段代码来处理一对多的查询

@Override@SuppressWarnings({"rawtypes", "unchecked"})public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,CriteriaBuilder builder) {Path expression;//此处是表关联数据,注意仅限一层关联,如user.address,//查询user的address集合中,address的name为某个值if (fieldName.contains(".")) {String[] names = StringUtils.split(fieldName, ".");//获取该属性的类型,Set?List?Map?expression = root.get(names[0]);Class clazz = expression.getJavaType();if (clazz.equals(Set.class)) {SetJoin setJoin = root.joinSet(names[0]);expression = setJoin.get(names[1]);} else if (clazz.equals(List.class)) {ListJoin listJoin = root.joinList(names[0]);expression = listJoin.get(names[1]);} else if (clazz.equals(Map.class)) {MapJoin mapJoin = root.joinMap(names[0]);expression = mapJoin.get(names[1]);} else {//是many to one时expression = expression.get(names[1]);}} else {//单表查询expression = root.get(fieldName);}

里面使用了SetJoin来完成对多的一方的某字段的匹配查询。
在Restrictions.java中,做了判断多的一方是基本类型还是JavaBean的判断:

/*** 集合包含某几个元素,譬如可以查询User类中Set<String> set包含"ABC","bcd"的User集合,* 或者查询User中Set<Address>的Address的name为"北京"的所有User集合* 集合可以为基本类型或者JavaBean,可以是one to many或者是@ElementCollection* @param fieldName* 列名* @param value* 集合* @return* expresssion*/public static LogicalExpression hasMembers(String fieldName, Object... value) {SimpleExpression[] ses = new SimpleExpression[value.length];int i = 0;//集合中对象是基本类型,如Set<Long>,List<String>Criterion.Operator operator = Criterion.Operator.IS_MEMBER;//集合中对象是JavaBeanif (fieldName.contains(".")) {operator = Criterion.Operator.EQ;}for (Object obj : value) {ses[i] = new SimpleExpression(fieldName, obj, operator);i++;}return new LogicalExpression(ses, Criterion.Operator.OR);}

同理,如果是使用one to many来映射的1对多表关系,同样可以使用上面的方法,写法也完全相同。

Criteria<PtSearchCondition> criteria = new Criteria<>();criteria.add(Restrictions.hasMembers("address.name", "北京"));criteria.add(Restrictions.hasMembers("provinces", "110000", "120000"));Page page = userRepository.findAll(criteria, new PageRequest(0, 10));

以上就能完成Jpa中1对多,根据多的一方的某属性进行过滤匹配。

JPA(hibernate)一对多根据多的一方某属性进行过滤查询相关推荐

  1. JPA Hibernate 注解

    1. @Entity(name="EntityName") 必须 ,name 为可选 , 对应数据库中一的个表 2. @Table(name="",catalo ...

  2. Hibernate一对多关联映射及cascade级联操作

    我们以客户(Customer)与订单(Order)为例 实体类创建 Order订单实体类 //订单-----多的一方 public class Order {private Integer id;pr ...

  3. JPA 一对一 一对多 多对一 多对多配置

    1 JPA概述 1.1 JPA是什么 JPA (Java Persistence API) Java持久化API.是一套Sun公司 Java官方制定的ORM 方案,是规范,是标准 ,sun公司自己并没 ...

  4. Hibernate一对多单向关联和双向关联映射方法及其优缺点

    一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同. 它们的区别在于维护的关系不同: 一对多关联映射是指在加载一的一端数据的 ...

  5. hibernate与jpa_将JPA Hibernate与OptaPlanner集成

    hibernate与jpa 我们一直在改进OptaPlanner与JEE其余部分的集成,因此更容易构建可以正常工作的最终用户应用程序. 让我们看一下改进的JPA Hibernate集成. 基础 JPA ...

  6. jpa jsf_完整的Web应用程序Tomcat JSF Primefaces JPA Hibernate –第1部分

    jpa jsf 我们创建了这篇文章,将展示如何使用以下工具创建完整的Web应用程序:Tomcat7,带有Primefaces的JSF2(Facelets和Libraries)(具有AutoComple ...

  7. jpa jsf_完整Web应用程序Tomcat JSF Primefaces JPA Hibernate –第2部分

    jpa jsf 托管豆 这篇文章是本教程第1部分的继续. 在" com.mb"包中,您将需要创建以下类: package com.mb;import org.primefaces. ...

  8. jpa jsf_完整的Web应用程序Tomcat JSF Primefaces JPA Hibernate –第3部分

    jpa jsf Primefaces AutoComplete,JSF转换器 这篇文章从第一部分和第二部分继续. JSF拥有Converter工具,可以帮助我们从用户视图中获取一些数据并将其转换为从数 ...

  9. 将JPA Hibernate与OptaPlanner集成

    我们一直在改进OptaPlanner与JEE其余部分的集成,因此,构建可以正常工作的最终用户应用程序更加容易. 让我们看一下改进的JPA Hibernate集成. 基础 JPA Hibernate和O ...

  10. JPA – Hibernate –包级别的类型映射

    当我们最终成熟到可以在JPA中使用某些自定义类型映射时,我们通常会停留在某些提供程序特定的解决方案上,因为JPA本身并未定义任何实现此功能的机制. 让我为您展示一个JPA提供程序Hibernate的自 ...

最新文章

  1. 网络推广——网络推广专员浅析网站建设中少不了对细节的关注
  2. Redis进阶-分布式存储 Sequential partitioning Hash partitioning
  3. 深度学习 点积的概念
  4. 爬楼梯—leetcode70
  5. 最激动人心的视觉系统其实是最枯燥乏味的
  6. offsetTop和scrollTop的差别
  7. Eclipse 导出
  8. 使用java实现rfc3161,openssl验证用自签名证书签名的RFC3161时间戳
  9. mysql解压版安装配置
  10. (三)Netty之Channel通道
  11. Java中如何判断一个字符串是否为数字
  12. 电脑编程教学_上村CNC电脑锣编程培训按工厂模式整套实训
  13. 【软件工程】北邮国际学院大三下期末复习
  14. html5 获取剪切板内容,H5剪切板功能
  15. php不能撤销,word无法撤销怎么解决
  16. RGB 透明度 对应代码
  17. 联想用u盘重装系统步骤_联想电脑怎样重新安装系统方法步骤详细教程 - 系统家园...
  18. 语音信号的基音参数提取
  19. Python自动化办公:word文件操作教程
  20. Lecture 9: Practical Tips for Final Projects

热门文章

  1. java注解生成xml和包含CDATA问题
  2. Qt编程之实现属性窗口编辑器
  3. Python写个小游戏:看图猜成语(上)
  4. Kali 利用setoolkit制作钓鱼网站
  5. 试验设计与方差分析的基本原理——以单因素试验为例
  6. 打印机服务器wps101官方网站,打印机服务器工具
  7. 我是 SPI,我让框架更加优雅了!
  8. 331. 验证二叉树的前序序列化
  9. c语言flag,[求助]int flag的意思
  10. 日子计算(结构+函数)