dromara / easy-query

java/kotlin high performance lightweight solution for jdbc query,support oltp and olap query,一款java下面支持强类型、轻量级、高性能的ORM,致力于解决jdbc查询,拥有对象模型筛选、隐式子查询、隐式join
http://www.easy-query.com
Apache License 2.0
518 stars 54 forks source link

子查询条件连接时, 若不按照 子表.子表字段 = 主表.主表字段拼接的话, 生成的语句会错误 #240

Open link2fun opened 3 months ago

link2fun commented 3 months ago
EasyPageResult<SysRole> pageResult = entityQuery.queryable(SysRole.class)
      .where((role) -> {
        role.delFlag().eq(UserConstants.NORMAL);
        role.roleId().eq(IdUtils.isIdValid(searchReq.getRoleId()), searchReq.getRoleId()); // 角色ID检索
        role.roleName().like(StrUtil.isNotBlank(searchReq.getRoleName()), searchReq.getRoleName()); // 角色名称检索
        role.status().eq(StrUtil.isNotBlank(searchReq.getStatus()), searchReq.getStatus()); // 角色状态检索
        role.roleKey().like(StrUtil.isNotBlank(searchReq.getRoleKey()), searchReq.getRoleKey()); // 角色权限检索
        role.createTime().ge(Objects.nonNull(searchReq.getParams().getBeginTime()), searchReq.getParams().getBeginTime()); // 开始时间检索
        role.createTime().le(Objects.nonNull(searchReq.getParams().getEndTime()), searchReq.getParams().getEndTime()); // 结束时间检索
      })
      .where(roleOuter -> {
        if (StrUtil.isNotBlank(searchReq.getParams().getDataScope())) {
          roleOuter.expression().exists(()->{

            return entityQuery.queryable(SysRole.class)
              .leftJoin(SysUserRole.class, (role, userRole) -> role.roleId().eq(userRole.roleId()))
              .leftJoin(SysUser.class, (role, userRole, user) -> userRole.userId().eq(user.userId())).asAlias(SysUser.TABLE_ALIAS)
              .leftJoin(SysDept.class, (role, userRole, user, dept) -> user.deptId().eq(dept.deptId())).asAlias(SysDept.TABLE_ALIAS)
              .where((role, userRole, user, dept) -> {
                role.expression().sql(searchReq.getParams().getDataScope()); // 数据范围过滤
//                roleOuter.roleId().eq(role.roleId()); // error fix me
                role.roleId().eq(roleOuter.roleId()); // success
              });
          });
        }
      })
      .select(SysRole.class)
//      .distinct()

      .toPageResult(page.getPageNum(), page.getPageSize());

如果 使用 主表.主表字段 = 子表.子表字段 生成的拼接条件有问题,示例语句

SELECT COUNT(*) 
FROM `sys_role` t
                WHERE t.`del_flag` = ? AND t.`role_id` = t1.`role_id`
                                    AND EXISTS (SELECT 1 FROM `sys_role` t1
                                        LEFT JOIN `sys_user_role` t2 ON t1.`role_id` = t2.`role_id`
                                        LEFT JOIN `sys_user` user ON t2.`user_id` = user.`user_id`
                                        LEFT JOIN `sys_dept` dept ON user.`dept_id` = dept.`dept_id`
                                                         WHERE ( dept.dept_id IN ( SELECT dept_id FROM sys_role_dept
                                                                                                  WHERE role_id = 2 ))
                                                         );

其中 表连接条件 t.role_id= t1.role_id` 跑到exists` 外面了

xuejmnet commented 3 months ago

感谢您的issue,这个本质而言确实应该是以内部表作为主表而不是外部表,这个问题确实存在并且可能一时半会还不一定好解决