MyBatis总结
mybatis xml和annotation有什么区别
MyBatis 是一个流行的 Java 持久层框架,它支持两种主要的 SQL 映射方式:XML 配置和注解(Annotation)。这两种方式各有优缺点,适用于不同的场景。以下是它们的核心区别:
1. 语法与定义位置
-
XML 配置:
- SQL 语句和映射关系定义在 XML 文件中(如
UserMapper.xml)。 - 需要在
mybatis-config.xml中注册映射文件,或通过注解@Mapper自动扫描。
- SQL 语句和映射关系定义在 XML 文件中(如
-
注解配置:
- SQL 语句直接写在接口方法上,使用
@Select、@Insert、@Update、@Delete等注解。 - 映射关系通过
@Results、@Result等注解定义在接口方法上。
- SQL 语句直接写在接口方法上,使用
2. 适用场景
-
XML 配置:
- 复杂 SQL:如动态 SQL(
<if>、<where>、<foreach>)、多表关联查询。 - SQL 经常变动:XML 文件修改无需重新编译 Java 代码。
- 团队协作:SQL 与 Java 代码分离,便于 DBA 或后端工程师维护。
- 复杂 SQL:如动态 SQL(
-
注解配置:
- 简单 SQL:如单表 CRUD 操作。
- 快速开发:减少 XML 文件数量,代码更简洁。
- 小型项目:SQL 逻辑简单,无需复杂映射。
3. 示例对比
场景:查询用户列表
XML 方式:
xml
<!-- UserMapper.xml -->
<select id="getUserList" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>
注解方式:
java
// UserMapper.java
@Select("SELECT * FROM users WHERE name = #{name} AND age = #{age}")
List<User> getUserList(@Param("name") String name, @Param("age") Integer age);
4. 动态 SQL 支持
-
XML:支持完整的动态 SQL,通过
<if>、<choose>、<set>等标签实现复杂逻辑。xml<select id="getUserList" resultType="User"> SELECT * FROM users <where> <if test="name != null">AND name = #{name}</if> <if test="age != null">AND age = #{age}</if> </where> </select> -
注解:动态 SQL 支持有限,需使用
@SelectProvider、@InsertProvider等注解结合 Java 代码实现。java@SelectProvider(type = UserSqlProvider.class, method = "getUserListSql") List<User> getUserList(String name, Integer age); class UserSqlProvider { public String getUserListSql(String name, Integer age) { StringBuilder sql = new StringBuilder("SELECT * FROM users WHERE 1=1"); if (name != null) sql.append(" AND name = #{name}"); if (age != null) sql.append(" AND age = #{age}"); return sql.toString(); } }
5. 结果映射
-
XML:通过
<resultMap>标签定义复杂映射关系。xml<resultMap id="userMap" type="User"> <id property="id" column="user_id"/> <result property="name" column="user_name"/> <collection property="orders" ofType="Order"> <id property="id" column="order_id"/> <result property="product" column="product_name"/> </collection> </resultMap> -
注解:通过
@Results、@Result、@One、@Many等注解定义映射。java@Results({ @Result(property = "id", column = "user_id"), @Result(property = "name", column = "user_name"), @Result(property = "orders", column = "user_id", many = @Many(select = "com.mapper.OrderMapper.getOrdersByUserId")) }) @Select("SELECT * FROM users WHERE id = #{id}") User getUserById(Integer id);
6. 维护性与扩展性
-
XML:
- 优点:SQL 与代码分离,适合复杂查询的维护;支持热更新(修改 XML 无需重启应用)。
- 缺点:XML 文件过多时管理成本高;IDE 对 XML 中的 SQL 智能提示较弱。
-
注解:
- 优点:代码集中,无需额外文件;IDE 对注解内 SQL 的语法检查和提示更友好。
- 缺点:SQL 逻辑复杂时,注解代码冗长,可读性下降。
7. 性能
两者在性能上无显著差异,MyBatis 最终都会将配置解析为
MappedStatement 对象。但 XML 方式可能因多一次文件读取导致极轻微延迟(可忽略不计)。8. 最佳实践
-
混合使用:
- 简单 SQL 使用注解,复杂 SQL 使用 XML。
- 通过
@Select引用 XML 中的<sql>片段:java@Select("SELECT * FROM users WHERE ${sql}") List<User> getUserByCustomSql(@Param("sql") String sql);
-
选择建议:
- 新项目:从注解开始,必要时迁移到 XML。
- 历史项目:已有大量 XML 配置时,保持现状或逐步重构。
总结
| 特性 | XML 配置 | 注解配置 |
|---|---|---|
| 定义位置 | XML 文件 | 接口方法上 |
| 适用场景 | 复杂 SQL、动态 SQL | 简单 SQL、快速开发 |
| 动态 SQL 支持 | 完整支持(标签) | 有限支持(需 Java 代码辅助) |
| 结果映射 | 复杂映射更清晰 | 简单映射更简洁 |
| 维护性 | SQL 与代码分离 | 代码集中 |
| IDE 支持 | SQL 提示较弱 | SQL 提示较强 |
根据项目规模、SQL 复杂度和团队习惯选择合适的方式,或混合使用以发挥两者优势。
浙公网安备 33010602011771号