public interface UserMapper extends BaseMapper<User> {
// 案例:查询指定部门下薪资最高的用户(假设需要复杂子查询) @Select("SELECT * FROM user WHERE dept_id = #{deptId} ORDER BY salary DESC LIMIT 1") User findTopSalaryUser(@Param("deptId") Long deptId);
// 案例:批量重置用户状态(用foreach处理集合) @Update("<script>" + "UPDATE user SET status = 0 WHERE id IN " + "<foreach item='id' collection='ids' open='(' separator=',' close=')'>" + "#{id}" + "</foreach>" + "</script>") int batchResetStatus(@Param("ids") List<Long> ids); }
<!-- 案例:带条件的分页联表查询 --> <select id="selectUserWithDept" resultType="com.yourpackage.vo.UserDeptVO"> SELECT u.id, u.name, u.age, d.name AS deptName FROM user u LEFT JOIN dept d ON u.dept_id = d.id <!-- 这里可以复用Wrapper的条件! --> ${ew.customSqlSegment} </select>
<select id="selectUserWithDept" resultType="UserDeptVO"> SELECT u.id AS userId, u.name AS userName, u.age, d.name AS deptName FROM user u LEFT JOIN dept d ON u.dept_id = d.id <!-- 关键!让Wrapper的条件生效 --> ${ew.customSqlSegment} </select>
步骤4:Service层调用
1 2 3 4 5 6 7
public List<UserDeptVO> searchUsers(String name, Long deptId, Integer minAge) { LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(name), User::getName, name) .eq(deptId != null, User::getDeptId, deptId) .ge(minAge != null, User::getAge, minAge); return userMapper.selectUserWithDept(wrapper); }
效果:
复用Wrapper的条件生成逻辑
自定义SQL处理联表查询
VO对象封装返回结果
四、避坑指南:血的教训总结
坑1:参数绑定问题
错误写法:
1 2
@Select("SELECT * FROM user WHERE name = #{name} AND age = #{age}") User findUser(String name, Integer age);
症状:当参数为null时,MyBatis可能抛出BindingException
正确姿势:
1 2
@Select("SELECT * FROM user WHERE name = #{name} AND age = #{paramAge}") // 用@Param别名 User findUser(@Param("name") String name, @Param("paramAge") Integer age);