当前位置: 首页 > news >正文

不同查询构建器的使用方式(Mybatis、Mybatis-Plus、Mybatis-Flex、Spring Data JPA、QueryDsl)

目录

    • 一、SQL查询需求
    • 二、【Mybaits】xml方式
    • 三、【Mybatis-Plus】QueryWrapper方式
    • 四、【Mybatis-Flex】QueryWrapper方式
    • 五、【Mybatis-Flex】QueryWrapper & APT方式
    • 六、【Spring Data JPA】Specification方式
    • 七、【Spring Data JPA】Specification & MetaModel方式
    • 八、【Spring Data JPA】QueryDsl方式

一、SQL查询需求

实现如下3个查询:

-- 查询1
SELECT 
* 
FROM SAMPLE 
WHERE
id = 1 
AND name LIKE '%ha%' 
AND create_time BETWEEN '2014-11-24' AND '2024-11-24'  -- 查询2
SELECT 
* 
FROM SAMPLE 
WHERE
id = 1 
OR name LIKE '%ha%' 
OR create_time BETWEEN '2014-11-24' AND '2024-11-24'  -- 查询3
SELECT 
* 
FROM SAMPLE 
WHERE
( id = 1 OR name LIKE '%ha%')
AND create_time BETWEEN '2014-11-24' AND '2024-11-24' 

查询参数:

package com.luo.query;class SampleQuery {private Long id;private String name;private LocalDateTime startDate;private LocalDateTime endDate;//省略getter/setter...
}

Sample数据对象:

package com.luo.po;class Sample {private Long id;private String name;private LocalDateTime createTime;//省略getter/setter...
}

二、【Mybaits】xml方式

定义dao接口:

package com.luo.dao;class SamplerMapper {List<Sample> select1(SampleQuery query);List<Sample> select2(SampleQuery query);List<Sample> select3(SampleQuery query);
}

定义mapper.xml,使用xml编写动态sql条件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.luo.dao.SampleMapper">   <select id="select1" resultType="com.luo.po.Sample">SELECT *FROM SAMPLE<where><if test="id != null">AND id = #{id}</if><if test="name != null">AND name LIKE CONCAT('%',#{name},'%')</if><if test="startDate != null and endDate != null">AND create_time BETWEEN #{startDate} AND #{endDate}</if></where></select><select id="select2" resultType="com.luo.po.Sample">SELECT *FROM SAMPLE<where><if test="id != null">OR id = #{id}</if><if test="name != null">OR name LIKE CONCAT('%',#{name},'%')</if><if test="startDate != null and endDate != null">OR create_time BETWEEN #{startDate} AND #{endDate}</if></where></select><select id="select3" resultType="com.luo.po.Sample">SELECT *FROM SAMPLE<where><if test="id != null or name != null">(<if test="id != null">id = #{id} OR </if><if test="name != null">name LIKE CONCAT('%',#{name},'%')</if>)</if>            <if test="startDate != null and endDate != null">AND create_time BETWEEN #{startDate} AND #{endDate}</if></where></select>
</mapper>

三、【Mybatis-Plus】QueryWrapper方式

定义dao接口,使用Mybatis-Plus QueryWrapper 动态构建查询条件:

import com.baomidou.mybatisplus.core.mapper.BaseMapper
import com.baomidou.mybatisplus.core.toolkit.Wrappers;public interface SampleMapper extends BaseMapper<Sample> {default List<Sample> select1(SampleQueryDto query) {return this.selectList(Wrappers.<Sample>lambdaQuery().eq(Objects.nonNull(query.getId()), Sample::getId, query.getId()).like(Objects.nonNull(query.getName()), Sample::getName, query.getName()).between(Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()), Sample::getCreateTime, query.getStartDate(), query.getEndDate()));}default List<Sample> select2(SampleQueryDto query) {return this.selectList(Wrappers.<Sample>lambdaQuery().or().eq(Objects.nonNull(query.getId()), Sample::getId, query.getId()).or().like(Objects.nonNull(query.getName()), Sample::getName, query.getName()).or().between(Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()), Sample::getCreateTime, query.getStartDate(), query.getEndDate()));}default List<Sample> select3(SampleQueryDto query) {return this.selectList(Wrappers.<Sample>lambdaQuery().between(Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()), Sample::getCreateTime, query.getStartDate(), query.getEndDate()).and(Objects.nonNull(query.getId()) || Objects.nonNull(query.getName()),wrapper -> wrapper.eq(Objects.nonNull(query.getId()), Sample::getId, query.getId()).or().like(Objects.nonNull(query.getName()), Sample::getName, query.getName())));}
}

四、【Mybatis-Flex】QueryWrapper方式

定义dao接口,使用Mybatis-Flex QueryWrapper 动态构建查询条件:

import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapperpublic interface SampleMapper extends BaseMapper<Sample> {default List<Sample> select1(SampleQueryDto query) {return this.selectListByQuery(QueryWrapper.create().eq(Sample::getId, query.getId(), Objects.nonNull(query.getId())).like(Sample::getName, query.getName(), Objects.nonNull(query.getName())).between(Sample::getCreateTime, query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())));}default List<Sample> select2(SampleQueryDto query) {return this.selectListByQuery(QueryWrapper.create().or(Sample::getId).eq(query.getId(), Objects.nonNull(query.getId())).or(Sample::getName).like(query.getName(), Objects.nonNull(query.getName())).or(Sample::getCreateTime).between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())));}default List<Sample> select3(SampleQueryDto query) {return this.selectListByQuery(QueryWrapper.create().between(Sample::getCreateTime, query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())).and(queryWrapper -> {queryWrapper.eq(Sample::getId, query.getId(), Objects.nonNull(query.getId())).or(Sample::getName).like(query.getName(), Objects.nonNull(query.getName()));}, Objects.nonNull(query.getId()) || Objects.nonNull(query.getName())));}
}

五、【Mybatis-Flex】QueryWrapper & APT方式

定义dao接口,使用Mybatis-Flex QueryWrapper 和 基于APT生成的查询辅助类 动态构建查询条件:

import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapper;
import static com.luo.po.table.SampleTableDef.SAMPLE;public interface SampleMapper extends BaseMapper<Sample> {default List<Sample> select1(SampleQueryDto query) {return this.selectListByQuery(QueryWrapper.create().where(SAMPLE.ID.eq(query.getId(), Objects.nonNull(query.getId()))).and(SAMPLE.NAME.like(query.getName(), Objects.nonNull(query.getName()))).and(SAMPLE.CREATE_TIME.between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()))));}default List<Sample> select2(SampleQueryDto query) {return this.selectListByQuery(QueryWrapper.create().where(SAMPLE.ID.eq(query.getId(), Objects.nonNull(query.getId()))).or(SAMPLE.NAME.like(query.getName(), Objects.nonNull(query.getName()))).or(SAMPLE.CREATE_TIME.between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()))));}default List<Sample> select3(SampleQueryDto query) {return this.selectListByQuery(QueryWrapper.create().where(SAMPLE.CREATE_TIME.between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()))).and(SAMPLE.ID.eq(query.getId(), Objects.nonNull(query.getId())).or(SAMPLE.NAME.like(query.getName(), Objects.nonNull(query.getName())))));}
}

六、【Spring Data JPA】Specification方式

定义仓库接口,使用Spring Data JPA Specification构建查询条件:

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.util.CollectionUtils;import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;/*** 示例仓库(Specification)** @author luohq* @date 2024-11-25 13:01* @link https://docs.spring.io/spring-data/jpa/reference/jpa/specifications.html*/
public interface SampleRepo1 extends JpaRepository<Sample, String>, JpaSpecificationExecutor<Sample>, QuerydslPredicateExecutor<Sample> {default List<Sample> select1(SampleQuery query) {//构建查询条件Specification<Sample> specification = new Specification<>() {@Overridepublic Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {List<Predicate> predicates = new ArrayList<>(3);if (Objects.nonNull(query.getId())) {predicates.add(cb.equal(root.get("id"), query.getId()));}if (Objects.nonNull(query.getName())) {predicates.add(cb.like(root.get("name"), "%" + query.getName() + "%"));}if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {predicates.add(cb.between(root.get("createTime"), query.getStartDate(), query.getEndDate()));}return cb.and(predicates.toArray(Predicate[]::new));}};//执行查询return this.findAll(specification);}default List<Sample> select2(SampleQuery query) {//构建查询条件Specification<Sample> specification = new Specification<>() {@Overridepublic Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {List<Predicate> predicates = new ArrayList<>(3);if (Objects.nonNull(query.getId())) {predicates.add(cb.equal(root.get("id"), query.getId()));}if (Objects.nonNull(query.getName())) {predicates.add(cb.like(root.get("name"), "%" + query.getName() + "%"));}if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {predicates.add(cb.between(root.get("createTime"), query.getStartDate(), query.getEndDate()));}if (CollectionUtils.isEmpty(predicates)) {//默认添加一个成立条件,避免多个or条件为空时拼接0=1predicates.add(cb.equal(cb.literal(1), 1));}return cb.or(predicates.toArray(Predicate[]::new));}};//执行查询return this.findAll(specification);}default List<Sample> select3(SampleQuery query) {//构建查询条件Specification<Sample> specification = new Specification<>() {@Overridepublic Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {List<Predicate> predicates = new ArrayList<>(2);if (Objects.nonNull(query.getId())) {predicates.add(cb.equal(root.get("id"), query.getId()));}if (Objects.nonNull(query.getName())) {predicates.add(cb.like(root.get("name"), "%" + query.getName() + "%"));}if (CollectionUtils.isEmpty(predicates)) {//默认添加一个成立条件,避免多个or条件为空时拼接0=1predicates.add(cb.equal(cb.literal(1), 1));}Predicate group1 = cb.or(predicates.toArray(Predicate[]::new));predicates = new ArrayList<>(1);if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {predicates.add(cb.between(root.get("createTime"), query.getStartDate(), query.getEndDate()));}Predicate group2 = cb.and(predicates.toArray(Predicate[]::new));return cb.and(group1, group2);}};//执行查询return this.findAll(specification);}
}

七、【Spring Data JPA】Specification & MetaModel方式

定义仓库接口,使用Spring Data JPA Specification 和 动态生成的JPA元模型 构建查询条件:

import com.luo.po.Sample;
import com.luo.po.Sample_;
import com.luo.query.SampleQuery;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.util.CollectionUtils;import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;/*** 示例仓库(Specification、MetaModel)** @author luohq* @date 2024-11-25 13:01* @link https://docs.spring.io/spring-data/jpa/reference/jpa/specifications.html* @link https://docs.jboss.org/hibernate/jpamodelgen/1.3/reference/en-US/html_single/*/
public interface SampleRepo2 extends JpaRepository<Sample, String>, JpaSpecificationExecutor<Sample>, QuerydslPredicateExecutor<Sample> {default List<Sample> select1(SampleQuery query) {//构建查询条件Specification<Sample> specification = new Specification<>() {@Overridepublic Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {List<Predicate> predicates = new ArrayList<>(3);if (Objects.nonNull(query.getId())) {predicates.add(cb.equal(root.get(Sample_.ID), query.getId()));}if (Objects.nonNull(query.getName())) {predicates.add(cb.like(root.get(Sample_.NAME), "%" + query.getName() + "%"));}if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {predicates.add(cb.between(root.get(Sample_.CREATE_TIME), query.getStartDate(), query.getEndDate()));}return cb.and(predicates.toArray(Predicate[]::new));}};//执行查询return this.findAll(specification);}default List<Sample> select2(SampleQuery query) {//构建查询条件Specification<Sample> specification = new Specification<>() {@Overridepublic Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {List<Predicate> predicates = new ArrayList<>(3);if (Objects.nonNull(query.getId())) {predicates.add(cb.equal(root.get(Sample_.ID), query.getId()));}if (Objects.nonNull(query.getName())) {predicates.add(cb.like(root.get(Sample_.NAME), "%" + query.getName() + "%"));}if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {predicates.add(cb.between(root.get(Sample_.CREATE_TIME), query.getStartDate(), query.getEndDate()));}if (CollectionUtils.isEmpty(predicates)) {//默认添加一个成立条件,避免多个or条件为空时拼接0=1predicates.add(cb.equal(cb.literal(1), 1));}return cb.or(predicates.toArray(Predicate[]::new));}};//执行查询return this.findAll(specification);}default List<Sample> select3(SampleQuery query) {//构建查询条件Specification<Sample> specification = new Specification<>() {@Overridepublic Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {List<Predicate> predicates = new ArrayList<>(2);if (Objects.nonNull(query.getId())) {predicates.add(cb.equal(root.get(Sample_.ID), query.getId()));}if (Objects.nonNull(query.getName())) {predicates.add(cb.like(root.get(Sample_.NAME), "%" + query.getName() + "%"));}if (CollectionUtils.isEmpty(predicates)) {//默认添加一个成立条件,避免多个or条件为空时拼接0=1predicates.add(cb.equal(cb.literal(1), 1));}Predicate group1 = cb.or(predicates.toArray(Predicate[]::new));predicates = new ArrayList<>(1);if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {predicates.add(cb.between(root.get(Sample_.CREATE_TIME), query.getStartDate(), query.getEndDate()));}Predicate group2 = cb.and(predicates.toArray(Predicate[]::new));return cb.and(group1, group2);}};//执行查询return this.findAll(specification);}
}

八、【Spring Data JPA】QueryDsl方式

定义仓库接口,使用 Spring Data JPA 和 QueryDsl 构建查询条件:

import com.luo.po.Sample;
import static com.luo.po.QSample.sample;
import com.luo.query.SampleQuery;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;/*** 示例仓库(Specification、QueryDsl)** @author luohq* @date 2024-11-25 13:01* @link https://docs.spring.io/spring-data/jpa/reference/jpa/specifications.html* @link https://docs.spring.io/spring-data/jpa/reference/repositories/core-extensions.html#core.extensions.querydsl*/
public interface SampleRepo3 extends JpaRepository<Sample, String>, JpaSpecificationExecutor<Sample>, QuerydslPredicateExecutor<Sample> {default List<Sample> select1(SampleQuery query) {//Predicate predicate = sample.id.eq(query.getId())//        .and(sample.name.contains(query.getName()))//        .and(sample.createTime.between(query.getStartDate(), query.getEndDate()));//构建查询条件List<BooleanExpression> predicates = new ArrayList<>();if (query.getId() != null) {predicates.add(sample.id.eq(query.getId()));}if (query.getName() != null) {predicates.add(sample.name.contains(query.getName()));}if (query.getStartDate() != null && query.getEndDate() != null) {predicates.add(sample.createTime.between(query.getStartDate(), query.getEndDate()));}//避免空指针异常if (predicates.isEmpty()) {predicates.add(Expressions.asBoolean(true).isTrue());}//合并查询条件BooleanExpression predicate = Expressions.allOf(predicates.toArray(new BooleanExpression[predicates.size()]));//执行查询Iterable<Sample> all = this.findAll(predicate);return StreamSupport.stream(all.spliterator(), false).collect(Collectors.toList());}default List<Sample> select2(SampleQuery query) {//Predicate predicate = sample.id.eq(query.getId())//        .or(sample.name.contains(query.getName()))//        .or(sample.createTime.between(query.getStartDate(), query.getEndDate()));//构建查询条件List<BooleanExpression> predicates = new ArrayList<>();if (query.getId() != null) {predicates.add(sample.id.eq(query.getId()));}if (query.getName() != null) {predicates.add(sample.name.contains(query.getName()));}if (query.getStartDate() != null && query.getEndDate() != null) {predicates.add(sample.createTime.between(query.getStartDate(), query.getEndDate()));}//避免空指针异常if (predicates.isEmpty()) {predicates.add(Expressions.asBoolean(true).isTrue());}//合并查询条件BooleanExpression predicate = Expressions.anyOf(predicates.toArray(new BooleanExpression[predicates.size()]));//执行查询Iterable<Sample> all = this.findAll(predicate);return StreamSupport.stream(all.spliterator(), false).collect(Collectors.toList());}default List<Sample> select3(SampleQuery query) {//Predicate predicate = sample.createTime.between(query.getStartDate(), query.getEndDate())//        .and(sample.id.eq(query.getId())//                .or(sample.name.contains(query.getName()))//        );//构建查询条件 - 分组1List<BooleanExpression> predicates = new ArrayList<>();if (query.getStartDate() != null && query.getEndDate() != null) {predicates.add(sample.createTime.between(query.getStartDate(), query.getEndDate()));}//避免空指针异常if (predicates.isEmpty()) {predicates.add(Expressions.asBoolean(true).isTrue());}//合并查询条件BooleanExpression group1 = Expressions.allOf(predicates.toArray(new BooleanExpression[predicates.size()]));//构建查询条件 - 分组2predicates = new ArrayList<>();if (query.getId() != null) {predicates.add(sample.id.eq(query.getId()));}if (query.getName() != null) {predicates.add(sample.name.contains(query.getName()));}//避免空指针异常if (predicates.isEmpty()) {predicates.add(Expressions.asBoolean(true).isTrue());}//合并查询条件BooleanExpression group2 = Expressions.anyOf(predicates.toArray(new BooleanExpression[predicates.size()]));//合并分组条件Predicate predicate = Expressions.allOf(group1, group2);//执行查询Iterable<Sample> all = this.findAll(predicate);return StreamSupport.stream(all.spliterator(), false).collect(Collectors.toList());}
}

http://www.mrgr.cn/news/78053.html

相关文章:

  • Linux网络——NAT/代理服务器
  • WebSocket详解、WebSocket入门案例
  • C++ 优先算法 —— 长度最小的子数组(滑动窗口)
  • 【热门主题】000065 探索人工智能学习框架:开启智能未来的钥匙
  • 学习Servlet(含义,作用)
  • P1 练习卷(C++4道题)
  • 【Unity基础】如何选择渲染管线?
  • Failed to find SV in PRN block of SINEX file (Name svnav.dat)
  • [OpenGL]使用OpenGL+OIT实现透明效果
  • 内存不足引发C++程序闪退崩溃问题的分析与总结
  • 2024 年:Kubernetes 包管理的新前沿
  • AI:电商平台销售效率提升的魔法钥匙
  • 深度学习笔记1:自动微分与神经网络实现(附代码)
  • Springboot 整合 Java DL4J 搭建智能问答系统
  • 小米C++ 面试题及参考答案下(120道面试题覆盖各种类型八股文)
  • Django 自定义路由转换器
  • 免费下载 | 2025中国5G产业全景图谱报告
  • Leetcode647. 回文子串(HOT100)
  • 【可解释性机器学习】基于SHAP进行特征选择和贡献度计算
  • AI-Talk开发板之Camera
  • OpenCV基础(3)
  • 优化Docker镜像:提升部署效率与降低资源消耗
  • Spring Boot 与 Java 决策树:构建智能分类系统
  • 数字逻辑(一)——导论
  • 241125学习日志——[CSDIY] [ByteDance] 后端训练营 [18]
  • 车载摄像camera基础知识和评估