DoytoQuery中的查询映射方案详解

目录
  • 引言
  • 四种字段映射方式详解
    • 1. 后缀映射
    • 2. OR映射
    • 3. 嵌套查询映射
    • 4. 直接映射
  • 总结
    • 附录I: 后缀支持列表

引言

DoytoQuery作为一个ORM框架,在研发过程中积累了很多全新的思路和解决方案,其中一个核心方案就是将查询对象的字段映射为SQL语句中的WHERE条件进行动态查询,目前支持四种字段映射方式。

让我们看看如何为以下UserEntity编写查询对象:

@Getter
@Setter
@Entity
public class UserEntity extends AbstractPersistable<Integer> {
    private String username;
    private String email;
    private String mobile;
    private String password;
    private String nickname;
    private Boolean valid;
}

四种字段映射方式详解

1. 后缀映射

先定义一个类UserQuery, 对于一些常见的查询条件,比如id = ?username = ? and valid = ?等,我们只需要在UserQuery类中定义如下字段即可。

@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class UserQuery extends PageQuery {
    private Integer id;
    private String username;
    private Boolean valid;
}

像其他一些常用的比较符号. [NOT] LIKE><!=>=<=IS [NOT] NULL[NOT] IN, 我们需要在列名后加一些特定的后缀作为字段名称来标识对应的条件符号。比如,将idIn映射为id IN (?,?,?), 将idGt映射为id > ?, 将usernameLike映射为username LIKE ?, 还需要定义好对应的类型。

public class UserQuery extends PageQuery {
    private Integer id;
    private String username;
    private Boolean valid;
    private List<Integer> idIn;
    private Integer idGt;
    private String usernameLike;
}

只有值不为NULL的字段才会被映射,并且多个条件由AND连接。

UserQuery userQuery = UserQuery.builder().usernameLike("test").valid(true).build();

这个userQuery会被映射为如下查询语句以及对应的参数。

SELECT id, username, email, mobile, password, nickname, valid FROM user WHERE username LIKE ? and valid = ?
-- With parameters: ["%test%", true]

所有支持的后缀详见附录I。

2. OR映射

OR语句也是SQL里一种常用的查询方式,DoytoQuery支持的方式有两种。

2.1 将含Or的字段映射为OR语句

usernameOrEmailOrMobile这样多个字段由Or连接的字段会被映射为username = ? OR email = ? OR mobile = ?

2.2 将实现了Or的对象映射为OR语句

public interface Or {
}
public class AccountOr implements Or {
    private String username;
    private String email;
    private String mobile;
}
public class UserQuery {
    private AccountOr account;
}

遍历AccountOr中的字段可以得到[username, email, mobile],然后使用关键字OR相连而得username = ? OR email = ? OR mobile = ?.

3. 嵌套查询映射

嵌套查询是SQL的另一个常用特性。在管理菜单树的menu表的常见定义中,我们通常定义一个外键parentId来引向父菜单实体的id

要查询拥有子菜单的父菜单,我们可以执行以下SQL:

SELECT * FROM menu WHERE id IN (SELECT parentId FROM menu WHERE ...)

要查询某些菜单的子菜单,我们可以执行以下SQL:

SELECT * FROM menu WHERE parentId IN (SELECT id FROM menu WHERE ...)

这条语句用于查询指定用户拥有的菜单:

SELECT * FROM menu WHERE id IN (
    SELECT menu_id FROM a_perm_and_menu WHERE perm_id IN (
        SELECT perm_id FROM a_role_and_perm WHERE role_id IN (
            SELECT role_id FROM a_user_and_role WHERE user_id IN (
                SELECT id FROM t_user WHERE id = ?
))))

这些都是ERM模型里常见的一对多/多对一/多对多关系. DoytoQuery定义了一个新的@DomainPath注解来映射这种嵌套查询。

@Target(FIELD)
@Retention(RUNTIME)
public @interface DomainPath {
    // To describe how to route from the host domain to the target domain.
    String[] value();
    String localField() default "id";
    String foreignField() default "id";
}

这里有一个@DomainPath注解用法介绍。

public class MenuQuery extends PageQuery {
    // 多对一: 根据父菜单的条件查询他们的子菜单
    @DomainPath(localField = "parentId", foreignField = "id", value = "menu")
    MenuQuery parent;      // parentId   IN (SELECT      id   FROM     menu  WHERE ... )
    // 一对多: 根据子菜单的条件查询父菜单
    @DomainPath(localField = "id", foreignField = "parentId", value = "menu")
    MenuQuery children;    // id   IN (SELECT      parentId   FROM     menu  WHERE ... )
    // 多对多: 查询满足条件的用户被授予的菜单
    @DomainPath({"menu", "~", "perm",  "~", "role", "~", "user"})
    UserQuery user;
}

4. 直接映射

当上述方法都不使用时,还有最后一种将字段映射到条件的方法,就是使用注解@QueryField定义查询条件后直接映射。这是DoytoQuery创建时的第一种映射方式,但是是最后一种推荐的方式,用法如下:

public class MenuQuery extends PageQuery {
    @QueryField(and = "id = (SELECT parent_id FROM menu WHERE id = ?)")
    private Integer childId;
}

嵌套查询的这种映射方式在@DomainPath发明后就已弃用。

总结

在本文中,我们介绍了DoytoQuery中的四种字段映射方式。前三种方式不需要编写任何SQL语句,并且可以涵盖到关系数据库开发中大部分涉及单表查询的场景。

附录I: 后缀支持列表

后缀名称 比较符号 占位符 类型 值处理
(No matching
suffix)
=
Not != ?
NotLike NOT LIKE ? String %value%
Like LIKE ? String %value%
Start LIKE ? String %value
End LIKE ? String value%
NotIn NOT IN
非空集合: (?[, ?]);
空集合则忽略

Collection
In IN
非空集合(?[, ?]);
空集合: (null)

Collection
NotNull IS NOT NULL - boolean
Null IS NULL - boolean
Gt > ?
Ge >= ?
Lt < ?
Le <= ?
Eq = ?

以上就是DoytoQuery中的查询映射方案详解的详细内容,更多关于DoytoQuery查询映射的资料请关注我们其它相关文章!

(0)

相关推荐

  • DoytoQuery 聚合查询方案示例详解

    目录 1. 引言 2. 聚合查询映射 2.1. 前缀映射 2.2. 分组聚合 2.3. HAVING 2.4. 动态查询 2.5. 查询接口定义 3. 完整示例 4. 总结 1. 引言 聚合查询是数据库提供的另一种常用的用于数据的统计和计算的查询功能,它通过提供一系列聚合函数来汇总来自多个行的信息. DoytoQuery采用字段前缀映射的方式来将字段名映射为聚合函数,再配合@GroupBy注解,Having接口以及Query对象,完成整条聚合查询语句的映射. 2. 聚合查询映射 2.1. 前缀映

  • DoytoQuery中的分页排序方案示例详解

    目录 引言 分页 分页接口 排序 请求对象 响应对象 小结 引言 分页和排序是数据库提供的两项基本的查询功能. 以MySQL为例,一条典型的SQL查询语句如下: SELECT * FROM t_user ORDER BY create_time DESC, username ASC LIMIT 10 OFFSET 20 那么在前后端交互中,前端应该如何向后端传递分页和排序有关的信息呢?需要传递哪些参数?参数的意义和格式又是什么? 分页 分页的语句为LIMIT 10 OFFSET 20,其中10为

  • MySQL详细讲解多表关联查询

    目录 数据库设计范式 外键 内连接 外连接 结语 数据库设计范式 目前数据库设计有五种范式 , 一般我们数据库只需要满足前三项即可 第一范式 : 确保每列保持原子性 什么是原子性? 意思就是不可再分的,例如下 联系方式有 QQ,微信 , 电话等等 , 显然此列不满足原子性, 如果是单独的QQ或者电话等,则只有一个, 满足第一范式 第二范式 : 要有主键,要求其他字段都依赖于主键 为什么主键这么重要? 我们可以这样理解, 如果把表当作一个队伍, 那么主键就是这个队伍的队旗 • 没有主键就没有唯一性

  • MybatisPlus实现对象嵌套关联查询一对多List集合查询

    目录 对象嵌套关联查询一对多List集合查询 mybatis嵌套关联查询如下 一对多查询(经典案例) 条件 数据库 代码实现 对象嵌套关联查询一对多List集合查询 mybatis嵌套关联查询如下 由于我的是一对集合查询,所以我有两个类. @Data @TableName("tb_user") public class User {     @TableId(type= IdType.INPUT)     private String id;     @TableField("

  • DoytoQuery中关于N+1查询问题解决方案详解

    目录 1. 背景 2. SQL层的解决方案 3. ORM应用层的解决方案 4. 小结 1. 背景 Java Persistence with Hibernate 在12.2.1小节使用如下例子描述 n+1查询问题: List<Item> items = em.createQuery("select i from Item i").getResultList(); // select * from ITEM for (Item item : items) { assertTr

  • DoytoQuery中的查询映射方案详解

    目录 引言 四种字段映射方式详解 1. 后缀映射 2. OR映射 3. 嵌套查询映射 4. 直接映射 总结 附录I: 后缀支持列表 引言 DoytoQuery作为一个ORM框架,在研发过程中积累了很多全新的思路和解决方案,其中一个核心方案就是将查询对象的字段映射为SQL语句中的WHERE条件进行动态查询,目前支持四种字段映射方式. 让我们看看如何为以下UserEntity编写查询对象: @Getter @Setter @Entity public class UserEntity extends

  • MyBatis中的JdbcType映射使用详解

    Java项目涉及到数据库交互,以往常用的是JDBC,现在则有Hibernate.Mybatis等这些持久化支持. 项目中用到了MyBatis,和JDBC最显著的区别,就是SQL语句配置化,通过xml文件定义SQL语句,当然JDBC也可以将SQL配置化,需要定制开发,MyBatis则直接支持这种方法. 官方对于MyBatis的介绍, MyBatis is a first class persistence framework with support for custom SQL, stored

  • 对Django项目中的ORM映射与模糊查询的使用详解

    ORM映射 什么是ORM映射?在笔者认为就是对SQL语句的封装,所写语句与SQL对应语句含义相同,使开发更加简单方便,不过也是存在弊端的,使程序运行效率下降.例如: UserInfo.objects.get(id=2) 等于 select * from user_userinfo where id=2 修改管理器(models.py) 导入新的包:from django.db import models 进行模糊查询 开始进行查找前我们先来认识filter()方法. 这是一个过滤器方法用于过滤掉

  • JS技巧多状态页面中的mock方案详解

    目录 引言 技术选型 业务逻辑改造 Eruda 插件 Mock 数据整理 引言 我们有时候会遇到一个业务页面存在很多个状态,甚至子状态,比如订单详情就是其中的典型,涉及从订单创建到订单结束,以及售后等流程.维护起来每个状态对应一份数据,虽然我们 QA 提供了数据构造平台,但构造一份对应状态的数据还是需要花费不少时间,而且串行流程一旦出错的话只能重新来一遍. 后期维护阶段也不容易构造对应状态的数据,导致排查页面问题比较耗时. 另外一个问题就是从头熟悉业务的话成本比较高,如果有一个直观的页面能够看到

  • Mybatis中的resultType和resultMap查询操作实例详解

    resultType和resultMap只能有一个成立,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,resultMap解决复杂查询是的映射问题.比如:列名和对象属性名不一致时可以使用resultMap来配置:还有查询的对象中包含其他的对象等. MyBatisConfig.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configura

  • Java中JDBC实现动态查询的实例详解

    一 概述 1.什么是动态查询? 从多个查询条件中随机选择若干个组合成一个DQL语句进行查询,这一过程叫做动态查询. 2.动态查询的难点 可供选择的查询条件多,组合情况多,难以一一列举. 3.最终查询语句的构成 一旦用户向查询条件中输入数据,该查询条件就成为最终条件的一部分. 二 基本原理 1.SQL基本框架 无论查询条件如何,查询字段与数据库是固定不变的,这些固定不变的内容构成SQL语句的基本框架,如 select column... from table. 2.StringBuilder形成D

  • Mybatis模糊查询及自动映射实现详解

    这篇文章主要介绍了Mybatis模糊查询及自动映射实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Mybatis的模糊查询 1. 参数中直接加入%% 1 2 3 4 5 6 7 8 9 param.setUsername("%CD%"); param.setPassword("%11%"); <select id="selectPersons" resultType="p

  • Spring拦截器中注入Bean失败解放方案详解

    目录 简介 问题重现 解决方案 简介 说明 本文用示例介绍如何解决拦截器中注入Bean失败的问题. 场景 Token拦截器中需要用@Autowired注入JavaJwtUtil类,结果发现注入的JavaJwtUtil为Null. 原因 拦截器的配置类是以new JwtInterceptor的方式使用的,那么这个JwtInterceptor不受Spring管理.因此,里边@Autowired注入JavaJwtUtil是不会注入进去的. 问题重现 代码 application.yml server:

  • thinkphp中的多表关联查询的实例详解

    thinkphp中的多表关联查询的实例详解 在进行后端管理系统的编程的时候一般会使用框架来进行页面的快速搭建,我最近使用比较多的就是thinkphp框架,thinkphp框架的应用其实就是把前端和后端进行分割管理,前端用户登录查询系统放在thinkphp中的home文件夹中进行管理,后端管理系统放在thinkphp中的admin文件夹中进行管理.对了,在使用thinkphp框架的时候是是要用到mvc架构的,mvc架构就是model(数据模型).view(视图).controller(控制器)的结

  • Yii2中hasOne、hasMany及多对多关联查询的用法详解

    前言 hasOne.hasMany是Yii2特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们.为什么?因为这种方式关联查询出来的结果会保留Yii2自有的表头排序功能,以及CheckboxColumn中input的id存值,至于还有没有其它的好处就需要大家去挖掘了,笔者目前就发现了这两个常用的好处.其他的关联查询,像yiidbQuery查询或者原生的SQL语句查询都没有,查询出来在列表展示的时候,表头一排黑. Yii2的hasOne.hasMany多表关联查询,不管是文档还是

随机推荐