1. MyBatis条件查询入门指南
作为Java开发者最常用的ORM框架之一,MyBatis在数据库操作方面提供了极大的灵活性。今天我要分享的是如何用MyBatis实现最简单的条件查询——这个看似基础的功能,实际上蕴含着MyBatis最核心的设计思想。
我刚接触MyBatis时,最困惑的就是如何优雅地实现条件查询。网上各种复杂的示例看得人眼花缭乱,但其实MyBatis的条件查询可以非常简单。下面我就用最直白的方式,带你快速上手MyBatis条件查询的几种实现方式。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础环境准备
2.1 项目依赖配置
首先确保你的项目已经引入了MyBatis核心依赖。如果是Maven项目,在pom.xml中添加:
xml复制<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
如果你使用的是Spring Boot,可以直接使用:
xml复制<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
2.2 数据库表准备
假设我们有一个用户表user,结构如下:
sql复制CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
age INT,
email VARCHAR(100)
);
3. 最简单的条件查询实现
3.1 使用注解方式实现
对于简单的条件查询,MyBatis提供了非常简洁的注解方式:
java复制@Select("SELECT * FROM user WHERE username = #{username}")
List<User> findByUsername(String username);
这种方式适合查询条件固定且简单的情况。只需要在接口方法上添加@Select注解,编写SQL语句,用#{参数名}的方式接收参数即可。
3.2 使用XML映射文件
更常见的做法是使用XML映射文件。首先定义Mapper接口:
java复制public interface UserMapper {
List<User> findByAgeGreaterThan(int age);
}
然后在对应的UserMapper.xml中:
xml复制<select id="findByAgeGreaterThan" resultType="com.example.User">
SELECT * FROM user WHERE age > #{age}
</select>
这种方式将SQL与Java代码分离,更易于维护复杂的SQL语句。
4. 动态条件查询进阶
4.1 使用标签实现动态查询
实际开发中,查询条件往往是动态的。MyBatis提供了强大的动态SQL功能:
xml复制<select id="findUsers" resultType="com.example.User">
SELECT * FROM user
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
4.2 多条件组合查询
有时我们需要根据不同的条件组合查询:
java复制List<User> searchUsers(@Param("username") String username,
@Param("minAge") Integer minAge,
@Param("maxAge") Integer maxAge);
对应的XML配置:
xml复制<select id="searchUsers" resultType="com.example.User">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="minAge != null">
AND age >= #{minAge}
</if>
<if test="maxAge != null">
AND age <= #{maxAge}
</if>
</where>
</select>
5. 条件查询的实用技巧
5.1 使用Map传递参数
对于参数较多的情况,可以使用Map传递参数:
java复制List<User> findUsersByMap(Map<String, Object> params);
XML配置:
xml复制<select id="findUsersByMap" resultType="com.example.User">
SELECT * FROM user
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
调用方式:
java复制Map<String, Object> params = new HashMap<>();
params.put("username", "张三");
params.put("age", 25);
List<User> users = userMapper.findUsersByMap(params);
5.2 使用@Param注解指定参数名
当方法有多个参数时,建议使用@Param注解明确指定参数名:
java复制List<User> findUsersByConditions(
@Param("name") String name,
@Param("minAge") Integer minAge,
@Param("maxAge") Integer maxAge);
这样在XML中就可以直接使用指定的参数名,避免混淆。
6. 常见问题与解决方案
6.1 条件查询返回空结果
当查询条件不匹配任何记录时,MyBatis会返回空集合而不是null。这是正常行为,调用方应该总是检查集合大小而不是判断null。
6.2 模糊查询的实现
实现模糊查询有几种方式:
xml复制<!-- 方式1:在Java代码中拼接% -->
username LIKE #{pattern}
<!-- 方式2:在SQL中拼接 -->
username LIKE CONCAT('%', #{keyword}, '%')
<!-- 方式3:使用$符号(不推荐,有SQL注入风险) -->
username LIKE '%${keyword}%'
推荐使用第二种方式,既安全又灵活。
6.3 处理特殊字符
如果查询条件中包含特殊字符如%,_等,需要进行转义:
java复制String keyword = "30%";
keyword = keyword.replace("%", "\\%")
.replace("_", "\\_");
或者在SQL中使用ESCAPE子句:
sql复制username LIKE '%30!%%' ESCAPE '!'
7. 性能优化建议
7.1 合理使用索引
确保查询条件中的字段已经建立了适当的索引。例如:
sql复制CREATE INDEX idx_user_username ON user(username);
CREATE INDEX idx_user_age ON user(age);
7.2 避免SELECT *
尽量指定需要查询的列,而不是使用SELECT *:
xml复制<select id="findUsers" resultType="com.example.User">
SELECT id, username, age FROM user
WHERE age > #{age}
</select>
7.3 分页查询
对于大量数据,一定要实现分页查询:
xml复制<select id="findUsersByPage" resultType="com.example.User">
SELECT * FROM user
WHERE age > #{age}
LIMIT #{offset}, #{pageSize}
</select>
或者使用MyBatis提供的RowBounds:
java复制List<User> users = sqlSession.selectList(
"com.example.mapper.UserMapper.findUsers",
params,
new RowBounds(offset, pageSize));
8. 高级条件查询技巧
8.1 使用实现多条件选择
xml复制<select id="findUsers" resultType="com.example.User">
SELECT * FROM user
<where>
<choose>
<when test="username != null">
AND username = #{username}
</when>
<when test="email != null">
AND email = #{email}
</when>
<otherwise>
AND status = 'ACTIVE'
</otherwise>
</choose>
</where>
</select>
8.2 使用实现IN查询
处理多个值的查询条件:
xml复制<select id="findUsersByIds" resultType="com.example.User">
SELECT * FROM user
WHERE id IN
<foreach item="id" collection="ids"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
8.3 动态排序
实现动态排序功能:
xml复制<select id="findUsers" resultType="com.example.User">
SELECT * FROM user
<if test="orderBy != null">
ORDER BY ${orderBy}
<if test="orderDirection != null">
${orderDirection}
</if>
</if>
</select>
注意:使用$而不是#来直接插入SQL片段,但要注意防范SQL注入风险。
9. 与MyBatis-Plus的条件查询对比
MyBatis-Plus提供了更简洁的条件查询方式:
java复制// 查询年龄大于25的用户
List<User> users = userMapper.selectList(
new QueryWrapper<User>()
.gt("age", 25)
);
// 多条件查询
List<User> users = userMapper.selectList(
new QueryWrapper<User>()
.like("username", "张")
.between("age", 20, 30)
);
MyBatis-Plus的这种方式更符合Java编程习惯,但底层仍然是基于MyBatis的动态SQL实现的。
10. 调试与日志
10.1 打印执行的SQL
在开发环境中,可以配置MyBatis打印执行的SQL:
properties复制# application.properties
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
或者使用Log4j配置:
xml复制<logger name="com.example.mapper" level="DEBUG"/>
10.2 使用MyBatis Log插件
如果你使用IntelliJ IDEA,可以安装MyBatis Log插件,它能将MyBatis执行的SQL和参数合并成可执行的SQL语句,方便调试。
11. 实际项目中的应用建议
11.1 封装通用查询方法
在实际项目中,建议封装一些通用的查询方法:
java复制public interface BaseMapper<T> {
List<T> selectByCondition(Condition condition);
PageInfo<T> selectPageByCondition(Condition condition);
}
11.2 使用DTO接收查询条件
避免直接在Mapper接口中使用多个参数,建议使用DTO对象:
java复制@Data
public class UserQueryDTO {
private String username;
private Integer minAge;
private Integer maxAge;
// 其他查询条件...
}
public interface UserMapper {
List<User> selectByQueryDTO(UserQueryDTO query);
}
11.3 缓存常用查询结果
对于不经常变化的数据,可以考虑使用MyBatis的二级缓存:
xml复制<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
或者在Service层实现缓存逻辑。
12. 总结与最佳实践
经过上面的介绍,相信你已经掌握了MyBatis条件查询的各种实现方式。在实际项目中,我有几点经验分享:
- 对于简单的固定条件查询,使用注解方式最为简洁
- 对于复杂的动态查询,XML配置方式更易于维护
- 始终考虑SQL注入安全问题,避免直接拼接SQL
- 合理使用MyBatis提供的动态SQL标签,减少代码量
- 对于大量数据,一定要实现分页查询
- 在开发环境开启SQL日志,方便调试
MyBatis的条件查询功能非常灵活强大,掌握好这些基础用法后,你可以应对绝大多数业务场景下的数据查询需求。
