一、核心区别原因
1. 代码与配置的分离
- 注解:SQL与Java代码耦合,适合简单场景。
- XML:SQL与Java代码解耦,符合「关注点分离」原则。
2. 动态SQL支持
- 注解:需借助脚本标签或
@SelectProvider,可读性差。 - XML:原生支持动态SQL标签(如
<if>、<foreach>),更直观。
3. 可维护性
- 注解:适合短小SQL,修改需重新编译代码。
- XML:长SQL或复杂逻辑更易维护,支持热加载。
二、具体实现对比
1. 基础查询
注解方式
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(int id);
}
XML方式
<!-- UserMapper.xml -->
<mapper namespace="com.example.UserMapper">
<select id="getUserById" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
2. 动态SQL
注解方式(使用<script>标签)
@Select("<script>" +
"SELECT * FROM users " +
"<where>" +
" <if test='name != null'>AND name = #{name}</if>" +
" <if test='email != null'>AND email = #{email}</if>" +
"</where>" +
"</script>")
List<User> findUsers(@Param("name") String name, @Param("email") String email);
XML方式(原生动态标签)
<select id="findUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
<if test="email != null">AND email = #{email}</if>
</where>
</select>
3. 关联查询
注解方式(@Results手动映射)
@Select("SELECT u.*, a.city FROM users u LEFT JOIN address a ON u.id = a.user_id")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "address.city", column = "city")
})
List<User> getUsersWithAddress();
XML方式(ResultMap定义)
<resultMap id="UserWithAddress" type="User">
<id property="id" column="id"/>
<result property="address.city" column="city"/>
</resultMap>
<select id="getUsersWithAddress" resultMap="UserWithAddress">
SELECT u.*, a.city FROM users u LEFT JOIN address a ON u.id = a.user_id
</select>
三、选择建议
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 简单、固定SQL | 注解 | 代码简洁,减少文件切换 |
| 复杂动态SQL | XML | 标签直观,易于维护 |
| 多表关联或结果集映射 | XML | ResultMap支持更灵活的嵌套映射 |
| 需要SQL复用 | XML | 通过<sql>标签定义公共片段 |
四、本质总结
- 注解:牺牲解耦性换取开发便捷性,适合快速原型或小型项目。
- XML:通过解耦提升可维护性,适合中大型项目或复杂SQL场景。
注意优先级:注解 > XML。