使用JPA怎么实现多表复杂查询
创始人
2024-12-22 07:22:29
0次

1. 名字2. ID3. 手机号这是一个单表的多条件复杂查询,由于是在几个属性中进行筛选,其中的属性的个数不知道有多少个,所以只需要利用Specification 查询就可以很方便的实现这个需求。 下面请看代码:场景:页面上通过条件筛选,查询用户列表

这里有3个条件 在页面上我设置的id分别为searchName,searchId,searchMobile。 由于这个是user表 所以userRepository 继承JpaSpecificationExecutor接口,随后我创建了一个封装条件的类

public class PageParam {  private Integer pageSize = 10;  private Integer pageNumber = 1;  private String searchName;  private String searchMobile;  private String searchId;}

由于我这个方法是直接分页的 所以pageNumber 和pageSize 也可以直接写入到这个类中,用于方便接收参数,主要是对下面3个参数的封装

Specification specification = new Specification() {  @Override  public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {    List list = new ArrayList();    if (StringUtils.isNotBlank(searchName)) {      list.add(cb.like(root.get("name").as(String.class), "%" + searchName + "%"));    }    if (StringUtils.isNotBlank(searchId)) {      list.add(cb.equal(root.get("id").as(Long.class), searchId));    }    if (StringUtils.isNotBlank(searchMobile)) {      list.add(cb.like(root.get("mobile").as(String.class), "%" + searchMobile + "%"));    }    Predicate[] p = new Predicate[list.size()];    return cb.and(list.toArray(p));  };};

这里因为都是一个表,所以只要root.get(‘N ‘)这个N对应所要查的 属性的名字就好,属性名 属性名 重要的事情说三遍。再接下来看一组多表的查询

栗子2:

这里有4张表

public class Living {  Long id;    @ManyToOne  @JsonIgnore  @JoinColumn(name = "actorId", foreignKey = @ForeignKey(name = "none", value =ConstraintMode.NO_CONSTRAINT))  public Actor actor;    @ManyToOne  @JsonIgnore  @JoinColumn(name = "regionId", foreignKey = @ForeignKey(name = "none", value =ConstraintMode.NO_CONSTRAINT))  public Region region;}  public class Actor {  Long id;    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)  @JoinColumn(name = "actorId")  @org.hibernate.annotations.ForeignKey(name = "none")  List livings = new ArrayList<>();    @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)  @org.hibernate.annotations.ForeignKey(name = "none")  @JoinColumn(name = "userDetailId", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))  UserDetail userDetail;    @Column(nullable = false)  @Enumerated(value = EnumType.ORDINAL)  ActorType actorType = ActorType.A;    public enum ActorType{    A,B,C  }}  public class UserDetail {  Long id;     @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)  @org.hibernate.annotations.ForeignKey(name = "none")  @JoinColumn(name = "actorId", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))  Actor actor;    String truename;}  public class Region {  Long id;    String name;    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)  @JoinColumn(name = "regionId")  @org.hibernate.annotations.ForeignKey(name = "none")  List Livings;}

现在要根据userdetai 种的 sex actor中的actortype 还有 region的id 为条件查询出满足条件的living。

public class PageParam {  private Integer pageSize = 10;  private Integer pageNumber = 1;  private Sex sex;  private ActorType actortype;  private Long cityid;

首先我还是封装了这样一个类,但是这里的泛型 我是直接给到了想要的查询结果的泛型,接下来 因为这里涉及到了一个 多表的查询 所以上面的单表查询的例子 已经不适合这个查询了,但是Criteria 的join方法 给我们提供了一个模式

Specification specification = new Specification() {  @Override  public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {    List list = new ArrayList();    if (null!=sex) {      Join join = root.join("actor", JoinType.LEFT);      list.add(cb.equal(join.get("userDetail").get("sex"), sex ));    }    if (null!=actortype) {      Join join = root.join("actor", JoinType.LEFT);      list.add(cb.equal(join.get("actorType"), actortype));    }    if (null!=cityid) {      Join join = root.join("region", JoinType.LEFT);      list.add(cb.equal(join.get("id"), cityid));    }    //Join join = root.join("bs", JoinType.LEFT);    //list.add(cb.equal(join.get("c").get("id"), id));    Predicate[] p = new Predicate[list.size()];    return cb.and(list.toArray(p));  };};

这里是我对条件进行的封装。jpa 的多条件查询 主要是根据Criteria 为我们提供的方法封装条件,然后根据 给条件定义的位置,再生成sql语句,之后完成查询。

不得不说的地方,在这个多表的查询中以下面这句为例

Join join = root.join("actor", JoinType.LEFT);list.add(cb.equal(join.get("userDetail").get("sex"), sex ));

jointype.LEFT主要是说最终的这个属性 是在哪个表中, 而前面的 “actor” 则表示 从living表中 查询的 第一步的查询,比如我给出的例子 是要查询出 living 中的 actor 然后是actor 中的userdetail 之后才是 userdetail中的 sex属性 所以下面的join.get(“userDetail”).get(“sex”) ,这里就是get出相应的属性,一直到你得到想要的属性为止。 接下来的两个属性 也同理,许多人多jpa 有很大的误解,认为jpa 的多表,多条件复杂查询,不如mybatis的查询,在之前我也是这么觉得,但自从通过jpa 实现了这个多表多条件的复杂查询之后,我觉得hibernate的复杂查询 不逊于mybatis ,尤其是对sql 语句不是很精通的 码农,虽然hibernate的门槛较高可jpa 恰恰降低了hibernate 所需要的门槛,希望大家可以通过我的经验,更方便的与数据库进行交互。

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...