DoytoQuery中的查询映射方案详解

 更新时间:2022年12月27日 16:17:56   作者:DOYToWin  
这篇文章主要为大家介绍了DoytoQuery中的查询映射方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

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!=?
NotLikeNOT LIKE?String%value%
LikeLIKE?String%value%
StartLIKE?String%value
EndLIKE?Stringvalue%
NotInNOT IN

非空集合: (?[, ?]);
空集合则忽略

Collection
InIN

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

Collection
NotNullIS NOT NULL-boolean
NullIS NULL-boolean
Gt>?
Ge>=?
Lt<?
Le<=?
Eq=?

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

相关文章

  • 详解关于Spring Cloud 框架热部署的方法

    详解关于Spring Cloud 框架热部署的方法

    本篇文章主要介绍了详解关于Spring Cloud 框架热部署的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • 深入浅出JAVA MyBatis-快速入门

    深入浅出JAVA MyBatis-快速入门

    这篇文章主要介绍了在今天这篇博文中,我将要介绍一下mybatis的框架原理,以及mybatis的入门程序,实现用户的增删改查,她有什么优缺点以及mybatis和hibernate之间存在着怎么样的关系,大家这些问题一起通过本文学习吧
    2021-06-06
  • 基于request.getAttribute与request.getParameter的区别详解

    基于request.getAttribute与request.getParameter的区别详解

    本篇文章小编为大家介绍,基于request.getAttribute与request.getParameter的区别详解。需要的朋友参考下
    2013-04-04
  • 一文带你了解Java排序算法

    一文带你了解Java排序算法

    这篇文章主要为大家详细介绍了Java中常见的三个排序算法:选择排序,冒泡排序和插入排序,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-08-08
  • 如何基于Springboot完成新增员工功能并设置全局异常处理器

    如何基于Springboot完成新增员工功能并设置全局异常处理器

    最近工作中遇到了做一个管理员工信息的功能,下面这篇文章主要给大家介绍了关于如何基于Springboot完成新增员工功能并设置全局异常处理器的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • 详解Java中的数组与字符串相关知识

    详解Java中的数组与字符串相关知识

    这篇文章主要介绍了详解Java中的数组与字符串相关知识,包括操作字符串的一些基本方法列举,需要的朋友可以参考下
    2015-09-09
  • java基础教程之拼图游戏的实现

    java基础教程之拼图游戏的实现

    拼图游戏大家应该都玩过,下面这篇文章主要给大家介绍了关于java基础教程之拼图游戏的实现方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-01-01
  • mybatis-plus 插入修改配置默认值的实现方式

    mybatis-plus 插入修改配置默认值的实现方式

    这篇文章主要介绍了mybatis-plus 插入修改配置默认值的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • java中static的用法及注意点

    java中static的用法及注意点

    在本篇文章里小编给大家整理的是一篇关于java中static的用法及注意点,有兴趣的朋友们可以学习下。
    2021-03-03
  • SpringBoot启动流程SpringApplication准备阶段源码分析

    SpringBoot启动流程SpringApplication准备阶段源码分析

    这篇文章主要为大家介绍了SpringBoot启动流程SpringApplication准备阶段源码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04

最新评论