JdbcTemplate和MyBatis的区别
在 Java 后端开发中,JdbcTemplate(Spring 框架提供)和 MyBatis(持久层框架)都是用于简化数据库操作的工具,但它们的设计理念、使用方式、灵活性和适用场景有显著差异。下面从核心定位、核心特性、使用方式、优缺点等维度进行全面对比
一、核心定位与设计理念
对比维度 | JdbcTemplate | MyBatis |
---|---|---|
所属框架 | Spring 框架内置(spring-jdbc 模块) | 独立的持久层框架(可与 Spring 整合) |
设计核心 | 封装 JDBC 细节,简化“模板化”SQL操作 | 专注于 SQL 与 Java 代码的解耦,支持 SQL 灵活定制 |
定位 | “轻量级 JDBC 工具”,无 ORM 特性 | “半自动化 ORM 框架”(需手动写 SQL,自动映射结果) |
核心目标 | 减少 JDBC 重复代码(如连接管理、异常处理) | 平衡 SQL 灵活性与代码简洁性,避免硬编码 SQL |
二、核心特性对比
特性 | JdbcTemplate | MyBatis |
---|---|---|
SQL 编写位置 | 硬编码在 Java 代码中(字符串形式) | 写在 XML 映射文件或 Java 注解中 |
参数映射 | 手动通过 ? 占位符传参(如 update("SELECT * FROM user WHERE id = ?", 1) ) | 支持 #{}(预编译,防注入) 和 ${}(字符串拼接) ,自动映射 Java 对象参数 |
结果集映射 | 需手动处理 ResultSet (如用 RowMapper 转 Java 对象) | 自动映射(SQL 列名与 Java 对象属性名匹配,支持自定义映射规则) |
动态 SQL | 无原生支持,需手动用字符串拼接(易出错、有注入风险) | 原生支持动态 SQL(<if> 、<foreach> 、<choose> 等标签),安全且灵活 |
缓存支持 | 无内置缓存,需依赖 Spring 缓存(如 @Cacheable ) | 内置一级缓存(SqlSession 级别)和二级缓存(Mapper 级别),支持整合第三方缓存(如 Redis) |
批量操作 | 支持但需手动调用 batchUpdate() ,代码较繁琐 | 支持 BatchExecutor ,配合 <foreach> 可简化批量插入/更新 |
存储过程调用 | 需手动处理 CallableStatement ,代码复杂 | 原生支持存储过程(<select statementType="CALLABLE"> ) |
XML 配置 | 无需额外 XML,依赖 Spring 配置文件(如数据源) | 需配置核心配置文件(mybatis-config.xml )和映射文件(XxxMapper.xml ) |
代码侵入性 | 高(SQL 与 Java 代码耦合) | 低(SQL 与 Java 代码分离) |
三、使用方式示例(以“查询用户”为例)
通过具体代码对比,更直观理解两者差异。
1. JdbcTemplate 实现
需先在 Spring 配置数据源(如 application.yml
),再注入 JdbcTemplate
:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.example.admin.entity.User;@Repository
public class UserDao {// 注入 Spring 自动配置的 JdbcTemplate@Autowiredprivate JdbcTemplate jdbcTemplate;// 查询单个用户public User getUserById(Long id) {// 1. SQL 硬编码在代码中String sql = "SELECT id, username, email FROM user WHERE id = ?";// 2. 手动用 RowMapper 映射 ResultSet 到 User 对象RowMapper<User> rowMapper = (rs, rowNum) -> {User user = new User();user.setId(rs.getLong("id"));user.setUsername(rs.getString("username"));user.setEmail(rs.getString("email"));return user;};// 3. 执行查询并返回结果return jdbcTemplate.queryForObject(sql, rowMapper, id);}
}
2. MyBatis 实现
分 3 步:定义 Mapper 接口、编写 XML 映射文件、配置 MyBatis(Spring Boot 中可自动配置)。
步骤 1:定义 Mapper 接口(无实现类)
import org.apache.ibatis.annotations.Mapper;
import com.example.admin.entity.User;@Mapper // 标记为 MyBatis Mapper 接口,Spring 自动扫描
public interface UserMapper {// 方法名与 XML 中 SQL 的 id 对应User getUserById(Long id);
}
步骤 2:编写 XML 映射文件(UserMapper.xml
)
放在 resources/mapper
目录下,SQL 与代码分离:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- namespace 对应 Mapper 接口全路径 -->
<mapper namespace="com.example.admin.mapper.UserMapper"><!-- id 对应接口方法名,resultType 指定返回值类型(自动映射) --><select id="getUserById" resultType="com.example.admin.entity.User">SELECT id, username, email FROM user WHERE id = #{id}<!-- #{id} 自动接收参数,预编译防 SQL 注入 --></select>
</mapper>
步骤 3:Service 层调用 Mapper
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.admin.entity.User;
import com.example.admin.mapper.UserMapper;@Service
public class UserService {@Autowiredprivate UserMapper userMapper; // 注入 Mapper 接口(MyBatis 动态代理生成实现类)public User getUserById(Long id) {return userMapper.getUserById(id); // 直接调用接口方法}
}
四、优缺点对比
框架 | 优点 | 缺点 |
---|---|---|
JdbcTemplate | 1. 轻量级,无额外依赖(仅依赖 Spring) 2. 学习成本低,上手快 3. 代码简洁(适合简单 SQL 操作) 4. 灵活控制 JDBC 细节(如自定义 ResultSet 处理) | 1. SQL 硬编码,维护困难(复杂项目中代码混乱) 2. 无动态 SQL 支持,拼接 SQL 易出错 3. 无自动映射,需手动写 RowMapper 4. 不支持缓存,批量操作繁琐 |
MyBatis | 1. SQL 与代码分离,维护性好 2. 原生动态 SQL,支持复杂查询 3. 自动参数/结果映射,减少重复代码 4. 内置缓存,提升性能 5. 支持存储过程、批量操作 | 1. 需额外学习 MyBatis 语法(XML 标签、配置规则) 2. 复杂业务(多表关联)需手动写 SQL,工作量大 3. 无完全自动化 ORM(对比 Hibernate) |
五、选型建议
根据项目规模、SQL 复杂度、团队技术栈选择:
场景 | 推荐框架 | 理由 |
---|---|---|
小型项目/工具类(如你之前的“在线工具集管理后台”初期) | JdbcTemplate | 需求简单,SQL 不复杂,无需额外学习成本,快速开发 |
中大型项目(多表关联、动态 SQL 多) | MyBatis | SQL 灵活定制,维护性好,支持动态 SQL 和缓存,适合复杂业务场景 |
团队不熟悉 MyBatis,更熟悉 Spring | JdbcTemplate | 降低学习成本,利用现有 Spring 技术栈 |
需频繁调整 SQL(如报表统计、复杂查询) | MyBatis | SQL 独立存储,修改无需重新编译代码,迭代效率高 |
简单 CRUD 操作占比高 | 可结合 MyBatis-Plus | MyBatis-Plus 是 MyBatis 的增强工具,提供“无 SQL CRUD”(如 baseMapper.insert(user) ),兼顾灵活性和效率 |
六、补充:MyBatis-Plus 简介
如果你使用 MyBatis,推荐搭配 MyBatis-Plus(简称 MP),它是 MyBatis 的“增强工具”,不改变 MyBatis 核心逻辑,却能大幅减少重复 CRUD 代码:
- 提供
BaseMapper
接口,内置insert
/deleteById
/updateById
/selectList
等方法,无需写 XML; - 支持 Lambda 表达式查询(如
query().eq(User::getId, 1).one()
); - 原生支持分页、批量操作、逻辑删除等功能。