Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JPA(hibernate)一对多根据多的一方某属性进行过滤查询

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

作者头像
天涯泪小武
发布于 2019-01-17 03:27:54
发布于 2019-01-17 03:27:54
5K00
代码可运行
举报
文章被收录于专栏:SpringCloud专栏SpringCloud专栏
运行总次数:0
代码可运行

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /**
     * 检索人
     */
    private Long userId;
    /**
     * 省、直辖市集合
     */
    @ElementCollection
    @CollectionTable
    private List<String> provinces;
    /**
     * 市、区集合
     */
    @ElementCollection
    @CollectionTable
    private List<String> cities;
    /**
     * 行业集合
     */
    @ElementCollection
    @CollectionTable
    private 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这样的写法(注意:需要导入上面提到的那篇文章的几个类,才能用下面的写法):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        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注解的,那么如何查询呢? 很简单,同样还是使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    Criteria<PtSearchCondition> criteria = new Criteria<>();
    criteria.add(Restrictions.hasMembers("address.name", "北京"));
    Page page = userRepository.findAll(criteria, new PageRequest(0, 10));

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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的判断:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
     * 集合包含某几个元素,譬如可以查询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;
        //集合中对象是JavaBean
        if (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对多表关系,同样可以使用上面的方法,写法也完全相同。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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对多,根据多的一方的某属性进行过滤匹配。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年11月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Springboot中对jpa动态查询条件的封装
jpa对于固定参数的条件查询比较简单,可以在Repository中直接用参数名来查询。但是对于不固定的参数查询就比较麻烦了,官方提供的是继承JpaSpecificationExecutor,然后自己拼接Specification。这一篇主要是对Specification进行封装,让写法更友好. 代码参考:http://lee1177.iteye.com/blog/1994295。感觉还不够完整,回头使用中再补上。
天涯泪小武
2019/01/17
3K0
Hibernate--Criteria Query and DetachedCriteria
Criteria Query通过面向对象的设计,将数据查询条件封装为一个对象。简单来说,Criteria Query可以看作是传统SQL的对象化表示,如: Criteria criteria=session.createCriteria(TUser.class); criteria.add(Expression.eq("name","Erica")); criteria.add(Expression.eq("sex",new Integer(1)); 这里的criteria实例本质上是对SQL“select
冷冷
2018/02/08
1.3K0
Spring-data-jpa(spring数据持久层解决规范)详解
  1、Spring-data-jpa的基本介绍:JPA诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,百度百科说是JDK为了实现ORM的天下归一,目前也是在按照这个方向发展,但是还没能完全实现。在ORM框架中,Hibernate是一支很大的部队,使用很广泛,也很方便,能力也很强,同时Hibernate也是和JPA整合的比较良好,我们可以认为JPA是标准,事实上也是,JPA几乎都是接口,实现都是Hibernate在做,宏观上面看,在JPA的统一之下Hibernate很良好的运行。
ZhangXianSheng
2019/05/28
3.2K0
七、hibernate中的持久层模板操作HibernateTemplate的用法「建议收藏」
利用模板操作来替换掉持久层的session,必须先将spring和hibernate之间进行整合,整合的applicationContext配置文件介绍在:
全栈程序员站长
2022/07/05
9470
QBC查询
1、基本语法 session.beginTransaction(); Criteria criteria = session.createCriteria(Person.class); SimpleExpression gt = Restrictions.eq("name","张三"); criteria.add(gt); List<Person> list = criteria.list(); A、     Criteria setFirstResult(int firstResult):设置查询返回的第
JMCui
2018/03/15
1.1K0
Hibernate Criterion
在查询方法设计上能够灵活的依据Criteria的特点来方便地进行查询条件的组装. Hibernate设计了CriteriaSpecification作为Criteria的父接口,以下提供了Criteria和DetachedCriteria.
全栈程序员站长
2022/07/13
8770
Spring学习笔记(三十一)——SpringBoot JPA优雅高效的工具:QueryHelp
有下面的一个问题: 如果需要一个接口,可以根据传进来的不确定的多个参数动态的,条件的查询数据,这个需要怎么处理呢? 其实这个问题在之前的做项目中也有遇到过,处理方法是使用MyBatis的配置语句动态进行拼接,有一种if-else的感觉,当时做这个需求还是挺麻烦的。
不愿意做鱼的小鲸鱼
2022/09/26
1.5K0
Spring学习笔记(三十一)——SpringBoot JPA优雅高效的工具:QueryHelp
数据库:Criteria与原生SQL查询
DetachedCriteria类和Criteria接口功能很类似,可以使用上述提到的方式(Criterion与Projection)设置查询条件,但两者的创建方式不同:Criteria必须由Session对象创建,而DetachedCriteria创建时不需要Session对象。因此DetachedCriteria可以在Session作用域之外构建,并添加一系列复杂条件,然后传递到具有Session环境的Dao方法中执行。DetachedCriteria的出现实现了“条件构建”和“查询执行”的分离。
用户10175992
2023/10/17
7860
SpringBoot整合Spring-data-jpa
文章目录 1. SpringBoot整合Spring data jpa 1.1. 依赖 1.2. 主键生成策略 1.3. 配置 1.4. 创建一个实体类 1.5. 基本的查询 1.6. 自定义查询@Query 1.6.1. 使用HQL语句查询 1.6.2. 使用sql语句查询 1.6.3. 删除和修改 1.7. 复杂条件查询 1.8. 分页查询 1.8.1. PageRequest 1.8.2. Page 1.8.3. 简单查询 1.8.4. 简单条件分页查询 1.8.5. 复杂条件分页查询 1.9.
爱撒谎的男孩
2019/12/31
1.7K0
Spring Data JPA 介绍和使用
Spring Data JPA是Spring基于Hibernate开发的一个JPA框架。如果用过Hibernate或者MyBatis的话,就会知道对象关系映射(ORM)框架有多么方便。但是Spring Data JPA框架功能更进一步,为我们做了 一个数据持久层框架几乎能做的任何事情。下面来逐步介绍它的强大功能。
乐百川
2022/05/05
3.9K0
Hibernate入门这一篇就够了
前言 本博文主要讲解介绍Hibernate框架,ORM的概念和Hibernate入门,相信你们看了就会使用Hibernate了! 什么是Hibernate框架? Hibernate是一种ORM框架,全称为 Object_Relative DateBase-Mapping,在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象! 为什么要使用Hibernate? 既然Hibernate是关于Java对象和关系数据库之间的联系的话,也就是我们MVC中的数据持久层->在编写程序中的DAO层… 首先
Java3y
2018/03/15
1.8K0
Hibernate入门这一篇就够了
【原创】纯干货,Spring-data-jpa详解,全方位介绍。
本篇进行Spring-data-jpa的介绍,几乎涵盖该框架的所有方面,在日常的开发当中,基本上能满足所有需求。这里不讲解JPA和Spring-data-jpa单独使用,所有的内容都是在和Spring整合的环境中实现。如果需要了解该框架的入门,百度一下,很多入门的介绍。在这篇文章的接下来一篇,会有一个系列来讲解mybatis,这个系列从mybatis的入门开始,到基本使用,和spring整合,和第三方插件整合,缓存,插件,最后会持续到mybatis的架构,源码解释,重点会介绍几个重要的设计模式,这样一个体系。基本上讲完之后,mybatis在你面前就没有了秘密,你能解决mybatis的几乎所有问题,并且在开发过程中相当的方便,驾轻就熟。
全栈程序员站长
2022/06/28
2.1K0
【原创】纯干货,Spring-data-jpa详解,全方位介绍。
还在用Mybatis? Spring Data JPA 让你的开发效率提升数倍!
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 JPA 技术实现,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增、删、改、查等在内的常用功能,易于扩展,极大提高开发效率。
微观技术
2021/03/11
2.8K0
还在用Mybatis? Spring Data JPA 让你的开发效率提升数倍!
《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来
本文主要介绍了如何利用Spring Boot和Spring Data JPA实现一个可扩展的持久层框架,并对代码进行了详细的解析。同时,本文还提供了对事务管理和数据查询优化的实用技巧。
I Teach You 我教你
2018/01/02
2.1K0
聊聊jpa的动态查询
使用springside的DynamicSpecifications,再把mvc的参数映射为SearchFilter,也可以自己实现一套端到端的动态查询。
code4it
2018/09/17
2.3K0
SSH框架之Hibernate第二篇
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
海仔
2019/09/18
5920
Hibernate_day03总结
Hibernate_day03总结 今日内容 l Hibernate的检索方式 l Hibernate的抓取策略 l Hibernate的批量检索 l 事务的并发问题 1.1 上次课内容回顾: Hibernate的持久类三种状态: * 瞬时态:没有唯一标识OID,没有被session管理 * 持久态:有唯一标识OID,被session管理 * 脱管态:有唯一标识OID,没有被session管理. * 状态转换: 瞬时态:new 获得. * 瞬时à持久:save/saveOrUpdate * 瞬时à脱管:
Java帮帮
2018/03/19
1.2K0
Hibernate_day03总结
Spring Data JPA 使用简解
Spring Data JPA 是一个强大的框架,它极大地简化了基于 JPA(Java Persistence API)进行数据访问层的开发。通过 Spring Data JPA,开发者几乎不需要编写实现代码,就能快速实现数据库操作。下面就简单介绍 Spring Data JPA 的部分概念和使用方法。
繁依Fanyi
2024/06/22
5690
day29_Hibernate学习笔记_01
  Hibernate:是一个数据持久化层的ORM框架。   Object:对象,java对象,此处特指JavaBean。   Relational:关系,二维表,数据库中的表。   Mapping:映射|映射元数据,对象中属性与表的字段存在的对应关系。
黑泽君
2018/10/11
1.3K0
day29_Hibernate学习笔记_01
Hibernate查询方式
load它不会去立刻查询而是生成一个代理对象由于没有去查询它只包含你给的OID,直到你用到其他属性才会去查询给你
木瓜煲鸡脚
2019/09/17
9330
Hibernate查询方式
相关推荐
Springboot中对jpa动态查询条件的封装
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验