# JoinStrQueryWrapper 字符串类型Join构造器
# 介绍
JoinStrQueryWrapper
是一个基于字符串字段名的Join查询构造器,它提供了与 JoinLambdaWrapper
相似的功能,但使用字符串而不是Lambda表达式来引用字段。这种方式在某些场景下更加灵活,特别适合动态查询构建。
# 特点
- 字符串字段引用:使用字符串字段名而不是Lambda表达式
- 完整的Join支持:支持LEFT JOIN、RIGHT JOIN、INNER JOIN等
- 智能别名机制:在join匿名函数中自动为字段添加关联表别名
- 丰富的查询条件:支持所有常见的查询条件(eq、ne、gt、like等)
- 字段别名支持:支持为查询字段设置别名
- 一对一和多对多映射:支持复杂的关联查询映射
- 与Lambda构造器互转:可以与
JoinLambdaWrapper
相互转换
# 智能别名机制
JoinStrQueryWrapper
具有智能的别名处理机制,可以大大简化代码编写:
# 自动别名规则
join方法参数:
- 第一个参数:实际表名(如
"users_age"
) - 第二个参数:关联字段名(如
"id"
),会自动添加关联表别名变成"age.id"
- 第一个参数:实际表名(如
join匿名函数内:
- 所有字段名自动添加当前关联表的别名前缀
w.eq("status", 1)
自动变成age.status = 1
w.select("ageName")
自动变成age.ageName
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");
});
# 注意事项
- 字段名规范:字段名需要与数据库字段名或实体字段名保持一致
- 表别名:在多表关联时建议使用表别名避免字段名冲突
- 类型转换:使用
toLambda()
和toStr()
方法可以在两种构造器之间转换 - 性能考虑:字符串构造器在编译时无法进行字段名校验,需要注意拼写错误
# 示例:完整的复杂查询
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