# JoinStrQueryWrapper 字符串类型Join构造器

# 介绍

JoinStrQueryWrapper 是一个基于字符串字段名的Join查询构造器,它提供了与 JoinLambdaWrapper 相似的功能,但使用字符串而不是Lambda表达式来引用字段。这种方式在某些场景下更加灵活,特别适合动态查询构建。

# 特点

  • 字符串字段引用:使用字符串字段名而不是Lambda表达式
  • 完整的Join支持:支持LEFT JOIN、RIGHT JOIN、INNER JOIN等
  • 智能别名机制:在join匿名函数中自动为字段添加关联表别名
  • 丰富的查询条件:支持所有常见的查询条件(eq、ne、gt、like等)
  • 字段别名支持:支持为查询字段设置别名
  • 一对一和多对多映射:支持复杂的关联查询映射
  • 与Lambda构造器互转:可以与 JoinLambdaWrapper 相互转换

# 智能别名机制

JoinStrQueryWrapper 具有智能的别名处理机制,可以大大简化代码编写:

# 自动别名规则

  1. join方法参数

    • 第一个参数:实际表名(如 "users_age"
    • 第二个参数:关联字段名(如 "id"),会自动添加关联表别名变成 "age.id"
  2. join匿名函数内

    • 所有字段名自动添加当前关联表的别名前缀
    • w.eq("status", 1) 自动变成 age.status = 1
    • w.select("ageName") 自动变成 age.ageName
  3. joinAnd方法内

    • 同样具有自动别名功能
    • 字段名会自动添加指定表的别名

# 示例对比

// 传统写法(需要手动添加别名)
wrapper.leftJoin("users_age", "age.id", "users.ageId", "age", w -> {
    w.eq("age.status", 1);
    w.select("age.ageName", "age.ageDoc");
});

// 智能别名写法(自动添加别名)
wrapper.leftJoin("users_age", "id", "users.ageId", "age", w -> {
    w.eq("status", 1);        // 自动变成 age.status = 1
    w.select("ageName", "ageDoc"); // 自动变成 age.ageName, age.ageDoc
});

# 基本用法

# 创建构造器

// 通过实体类创建
JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);

// 通过实体实例创建
Users user = new Users();
JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(user);

// 指定别名
JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class, "u");

# 基本查询

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.select("userId", "userName", "createTime")
       .eq("status", 1)
       .like("userName", "张")
       .between("createTime", startTime, endTime);

List<Users> userList = usersService.joinList(wrapper, Users.class);

# 带别名的查询

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class, "u");
wrapper.selectWithAlias("u", "userId", "userName")
       .eq("u.status", 1);

# Join操作

# LEFT JOIN

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.select("userId", "userName")
       .leftJoin("users_age", "id", "users.ageId", "age", w -> {
           // 在join的匿名函数中,字段名会自动添加关联表别名(age)
           w.eq("status", 1);  // 等同于 age.status = 1
           w.select("ageName", "ageDoc");  // 等同于 age.ageName, age.ageDoc
       });

List<UsersVo> result = usersService.joinList(wrapper, UsersVo.class);

生成的SQL:

SELECT users.user_id, users.user_name, age.age_name, age.age_doc
FROM users users
LEFT JOIN users_age age ON age.id = users.age_id AND age.status = 1

重要说明

  • 表名参数:第一个参数 "users_age" 是实际的表名
  • 关联字段自动别名:第二个参数 "id" 会自动添加关联表别名,实际生成 age.id
  • 匿名函数自动别名:在join的匿名函数中,所有字段名(如 "status""ageName")都会自动添加关联表别名前缀

# RIGHT JOIN 和 INNER JOIN

// RIGHT JOIN
wrapper.rightJoin("users_role", "userId", "users.userId", "role", w -> {
    w.eq("status", 1);  // 自动添加别名: role.status = 1
    w.select("roleName", "roleCode");  // 自动添加别名: role.roleName, role.roleCode
});

// INNER JOIN
wrapper.innerJoin("users_dept", "userId", "users.userId", "dept", w -> {
    w.isNotNull("deptName");  // 自动添加别名: dept.deptName IS NOT NULL
    w.select("deptName", "deptCode");  // 自动添加别名: dept.deptName, dept.deptCode
});

# 字段查询与别名

# selectAs - 字段别名

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.leftJoin("users_age", "id", "users.ageId", "age", null)
       .select("userId", "userName")
       .selectAs("age.ageName", "userAgeName")
       .selectAs("age.ageDoc", "userAgeDoc");

# select - 多字段查询

// 基本字段查询
wrapper.select("userId", "userName", "createTime");

// 带表别名的字段查询
wrapper.select("u.userId", "u.userName", "age.ageName");

// 查询所有字段
wrapper.selectAll();

# 查询条件

# 基本条件

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.eq("status", 1)                    // 等于
       .ne("deleteFlag", 1)                // 不等于
       .gt("age", 18)                      // 大于
       .ge("age", 18)                      // 大于等于
       .lt("age", 65)                      // 小于
       .le("age", 65)                      // 小于等于
       .like("userName", "张")              // 模糊查询
       .notLike("userName", "admin")       // 不包含
       .likeLeft("userName", "张")         // 左模糊
       .likeRight("userName", "张")        // 右模糊
       .isNull("deleteTime")               // 为空
       .isNotNull("createTime")            // 不为空
       .in("status", Arrays.asList(1, 2))  // 在...之中
       .notIn("status", Arrays.asList(0))  // 不在...之中
       .between("createTime", start, end); // 在...之间

# 跨表条件

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.leftJoin("users_age", "id", "users.ageId", "age", w -> {
           w.eq("status", 1)  // 自动添加别名: age.status = 1
            .gt("age", 18);   // 自动添加别名: age.age > 18
       })
       .eq("users.status", 1);  // 主表条件需要显式指定别名

# 排序与分组

# 排序

wrapper.orderByAsc("createTime")           // 升序
       .orderByDesc("updateTime")          // 降序
       .orderBySql("FIELD(status, 1, 2, 0)"); // 自定义排序SQL

# 分组

wrapper.groupBy("deptId", "status")
       .having("count(*) > 5");

# 关联查询映射

# 一对一映射

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.leftJoin("users_age", "id", "users.ageId", "age", null)
       .oneToOneSelect("userAge", "age"); // 映射到 userAge 字段

List<UsersVo> result = usersService.joinList(wrapper, UsersVo.class);

# 多对多映射

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.leftJoin("user_roles", "userId", "users.userId", "ur", null)
       .leftJoin("roles", "id", "ur.roleId", "r", null)
       .manyToManySelect("roles", "r"); // 映射到 roles 集合字段

List<UsersVo> result = usersService.joinList(wrapper, UsersVo.class);

# 子查询

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.selectSub("SELECT COUNT(*) FROM orders WHERE orders.userId = users.userId", "orderCount")
       .select("userId", "userName");

# 与Lambda构造器转换

# 转换为Lambda构造器

JoinStrQueryWrapper<Users> strWrapper = new JoinStrQueryWrapper<>(Users.class);
strWrapper.eq("status", 1);

// 转换为Lambda构造器
JoinLambdaWrapper<Users> lambdaWrapper = strWrapper.toLambda();

# 从Lambda构造器转换

JoinLambdaWrapper<Users> lambdaWrapper = new JoinLambdaWrapper<>(Users.class);
lambdaWrapper.eq(Users::getStatus, 1);

// 转换为字符串构造器
JoinStrQueryWrapper<Users> strWrapper = lambdaWrapper.toStr();

# 高级用法

# joinAnd - 添加关联条件

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class);
wrapper.leftJoin("users_age", "id", "users.ageId", "age", null)
       .joinAnd("age", w -> {
           // joinAnd中的字段名也会自动添加指定表的别名
           w.gt("age", 18)     // 自动添加别名: age.age > 18
            .eq("status", 1);  // 自动添加别名: age.status = 1
       });

# distinct - 去重

wrapper.distinct()
       .select("userName", "deptId");

# 条件分组

wrapper.and(w -> {
    w.eq("status", 1)
     .or()
     .eq("status", 2);
}).or(w -> {
    w.like("userName", "admin")
     .like("realName", "admin");
});

# 注意事项

  1. 字段名规范:字段名需要与数据库字段名或实体字段名保持一致
  2. 表别名:在多表关联时建议使用表别名避免字段名冲突
  3. 类型转换:使用 toLambda()toStr() 方法可以在两种构造器之间转换
  4. 性能考虑:字符串构造器在编译时无法进行字段名校验,需要注意拼写错误

# 示例:完整的复杂查询

JoinStrQueryWrapper<Users> wrapper = new JoinStrQueryWrapper<>(Users.class, "u");
wrapper.select("u.userId", "u.userName", "u.createTime")
       .leftJoin("users_age", "id", "u.ageId", "age", w -> {
           w.eq("status", 1);  // 自动添加别名: age.status = 1
           w.select("ageName"); // 自动添加别名: age.ageName
       })
       .leftJoin("users_dept", "id", "u.deptId", "dept", w -> {
           w.select("deptName"); // 自动添加别名: dept.deptName
       })
       .selectAs("age.ageName", "userAge")
       .selectAs("dept.deptName", "deptName")
       .eq("u.status", 1)
       .like("u.userName", "张")
       .gt("age.age", 18)
       .isNotNull("dept.deptName")
       .orderByDesc("u.createTime")
       .orderByAsc("age.age");

List<UsersVo> result = usersService.joinList(wrapper, UsersVo.class);

生成的SQL:

SELECT u.user_id, u.user_name, u.create_time, 
       age.age_name AS userAge, dept.dept_name AS deptName
FROM users u
LEFT JOIN users_age age ON age.id = u.age_id AND age.status = 1
LEFT JOIN users_dept dept ON dept.id = u.dept_id
WHERE u.status = 1 
  AND u.user_name LIKE '%张%' 
  AND age.age > 18 
  AND dept.dept_name IS NOT NULL
ORDER BY u.create_time DESC, age.age ASC