1.在 MyBatis-Plus 中,QueryWrapper 是一个非常强大的工具,用于动态构建 SQL 查询条件。虽然 MyBatis-Plus 提供了很多便捷的内置方法(如 selectOne、selectList 等),但在某些复杂场景下,你可能需要在 XML 文件中自定义 SQL,并结合 QueryWrapper 来实现动态查询。本回答将详细讲解如何在 MyBatis-Plus 的 XML 文件中实现 QueryWrapper 查询。
QueryWrapper:
QueryWrapper 是 MyBatis-Plus 提供的一个条件构造器,可以通过链式调用的方式动态生成 WHERE 条件。它适用于简单的查询场景,也可以通过与 XML 文件结合来处理更复杂的 SQL。
XML 文件:
在 MyBatis-Plus 中,虽然大部分 CRUD 操作可以通过 BaseMapper 自动实现,但对于复杂查询(例如多表联查、自定义聚合函数等),仍需在 XML 文件中编写 SQL。
结合方式:
通过在 Mapper 接口中定义方法,并在 XML 文件中使用 ${ew.customSqlSegment} 或 #{ew.sqlSelect} 等占位符,将 QueryWrapper 的动态条件嵌入到自定义 SQL 中。
public interface UserMapper extends BaseMapper<User> {
// 自定义查询方法,结合 QueryWrapper
List<User> selectUsersByWrapper(@Param("ew") QueryWrapper<User> queryWrapper);
// 分页查询方法,结合 QueryWrapper
IPage<User> selectUsersPage(Page<User> page, @Param("ew") QueryWrapper<User> queryWrapper);
}
注意:
@Param(“ew”) 是必须的,用于在 XML 中引用 QueryWrapper。
ew 是 MyBatis-Plus 的默认占位符名称,表示 “entity wrapper”。
2. 编写 XML 文件
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUsersByWrapper" resultType="com.example.entity.User">
SELECT * FROM user
WHERE 1=1
${ew.customSqlSegment}
select>
<select id="selectUsersPage" resultType="com.example.entity.User">
SELECT * FROM user
WHERE 1=1
${ew.customSqlSegment}
select>
mapper>
说明:
${ew.customSqlSegment}:
这是 MyBatis-Plus 提供的占位符,用于动态插入 QueryWrapper 生成的 WHERE 条件。它会自动包含 WHERE 关键字(如果有条件),因此在 SQL 中需要以 WHERE 1=1 开头,避免语法错误。
resultType:
指定返回的实体类类型,与 User 实体类对应。
public interface UserMapper extends BaseMapper<User> {
// 多表联查,返回自定义 VO 对象
List<UserRoleVO> selectUserRoleList(@Param("ew") QueryWrapper<User> queryWrapper);
// 分页多表联查
IPage<UserRoleVO> selectUserRolePage(Page<User> page, @Param("ew") QueryWrapper<User> queryWrapper);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUserRoleList" resultType="com.example.vo.UserRoleVO">
SELECT
u.id,
u.name,
u.age,
r.role_name AS roleName
FROM user u
LEFT JOIN role r ON u.role_id = r.id
WHERE 1=1
${ew.customSqlSegment}
select>
<select id="selectUserRolePage" resultType="com.example.vo.UserRoleVO">
SELECT
u.id,
u.name,
u.age,
r.role_name AS roleName
FROM user u
LEFT JOIN role r ON u.role_id = r.id
WHERE 1=1
${ew.customSqlSegment}
select>
mapper>
JOIN 语句:
使用 LEFT JOIN 将 user 表和 role 表关联,关联条件是 u.role_id = r.id。
字段别名:
使用 r.role_name AS roleName 确保字段名与 UserRoleVO 中的属性一致。
${ew.customSqlSegment}:
动态插入 QueryWrapper 生成的 WHERE 条件,WHERE 1=1 是为了避免条件为空时的语法错误。
resultType:
指定返回类型为 UserRoleVO,MyBatis 会自动将查询结果映射到该对象
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 示例 1:查询用户和角色信息列表
public List<UserRoleVO> getUserRoleList(String name, String roleName) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// 动态条件:用户表字段
if (name != null && !name.isEmpty()) {
queryWrapper.like("u.name", name); // 注意表别名 u
}
// 动态条件:角色表字段
if (roleName != null && !roleName.isEmpty()) {
queryWrapper.like("r.role_name", roleName); // 注意表别名 r
}
queryWrapper.orderByDesc("u.id"); // 按用户 ID 降序
return userMapper.selectUserRoleList(queryWrapper);
}
// 示例 2:分页查询用户和角色信息
public IPage<UserRoleVO> getUserRolePage(int pageNum, int pageSize, String name, String roleName) {
Page<User> page = new Page<>(pageNum, pageSize);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (name != null && !name.isEmpty()) {
queryWrapper.like("u.name", name);
}
if (roleName != null && !roleName.isEmpty()) {
queryWrapper.like("r.role_name", roleName);
}
return userMapper.selectUserRolePage(page, queryWrapper);
}
}
表别名:
在 QueryWrapper 中使用条件时,需要加上表别名(如 u.name、r.role_name),与 XML 中的 SQL 保持一致。
分页:
分页功能由 MyBatis-Plus 的分页插件自动处理,只需传入 Page 对象即可。
最后想学习的可以加入java技术交流群QQ:1136472646