一、MyBatis 核心介绍
1.1 什么是框架
框架(Framework)是软件开发的 "半成品",它封装了基础代码并提供标准化 API,开发者基于框架开发可省去重复编码工作,大幅提升开发效率。
如果把成品软件比作装修好的新房,框架就像毛坯房 —— 提供基础结构,保证核心质量,开发者只需专注于业务逻辑(装修)即可。
1.2 框架要解决的核心问题
框架最核心的价值是技术整合与解耦。在 J2EE 体系中,技术选型多样且复杂,框架能将应用设计与底层技术实现分离,让研发聚焦于业务设计,而非技术细节。
1.3 传统 JDBC 的痛点
先看一段传统 JDBC 代码:
public class JdbcTest {
public static void main(String[] args) {
try {
//1.加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
String url = "jdbc:mysql://192.168.10.137:3306/ssm";
Connection connection = DriverManager.getConnection(url, "root", "1111");
String sql = "select * from account";
//3.准备PreparedStatement对象
PreparedStatement pst = connection.prepareStatement(sql);
//4.执行sql语句
ResultSet rs = pst.executeQuery();
//5.遍历结果集
while(rs.next()){
Integer id = rs.getInt("id");
String name = rs.getString("name");
Double money = rs.getDouble("money");
System.out.println(id + " " + name + " " + money);
}
//6.关闭资源
rs.close();
pst.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
传统 JDBC 存在三大核心问题:
- 手动创建 / 释放数据库连接,资源管理繁琐
- SQL 语句硬编码在代码中,维护成本高
- 结果集解析重复且冗余,代码复用性差
1.4 MyBatis 框架概述
MyBatis 是一款优秀的持久层框架,它对 JDBC 进行封装,让开发者只需关注 SQL 本身,无需处理注册驱动、创建连接、参数设置、结果集解析等繁琐操作。
MyBatis 前身是 Apache 的 iBatis,2010 年迁移至 Google Code 并更名,核心定位是简化数据库操作,专注 SQL 层开发。
二、MyBatis 入门案例
2.1 环境准备
(1)Maven 依赖配置(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hg</groupId>
<artifactId>01_mybatis_HelloWorld</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!– MyBatis核心依赖 –>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!– MySQL驱动 –>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!– 日志依赖 –>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!– 单元测试 –>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<!– 加载java目录下的xml配置文件 –>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
(2)日志配置(log4j.properties)
properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] – %m%n
2.2 核心代码实现
(1)实体类(User.java)
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// Getter & Setter
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public Date getBirthday() { return birthday; }
public void setBirthday(Date birthday) { this.birthday = birthday; }
public String getSex() { return sex; }
public void setSex(String sex) { this.sex = sex; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\\'' +
", birthday=" + birthday +
", sex='" + sex + '\\'' +
", address='" + address + '\\'' +
'}';
}
}
(2)DAO 接口(UserMapper.java)
public interface UserMapper {
/**
* 查询所有用户
* @return 用户列表
*/
public List<User> findAll();
}
(3)Mapper 映射文件(UserMapper.xml)
<?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 namespace="com.hg.dao.UserMapper">
<!–
id:接口方法名
resultType:返回值类型
–>
<select id="findAll" resultType="com.hg.pojo.User">
select * from user
</select>
</mapper>
(4)MyBatis 核心配置(mybatis-config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!– 环境配置 –>
<environments default="dev">
<environment id="dev">
<!– 事务管理:JDBC原生事务 –>
<transactionManager type="JDBC"></transactionManager>
<!– 数据源:连接池 –>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="1111"/>
</dataSource>
</environment>
</environments>
<!– 加载Mapper映射文件 –>
<mappers>
<mapper resource="com/hg/dao/UserMapper.xml"/>
</mappers>
</configuration>
2.3 测试代码
public class MyBatisTest {
private InputStream inputStream;
private SqlSession sqlSession;
@Before
public void createSqlSession() throws IOException {
// 1.加载配置文件
String resource = "mybatis-config.xml";
inputStream = Resources.getResourceAsStream(resource);
// 2.创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3.获取SqlSession
sqlSession = sqlSessionFactory.openSession();
}
@Test
public void testFindAll(){
// 4.获取Mapper代理对象
UserDao userDao = sqlSession.getMapper(UserMapper.class);
// 5.执行查询
List<User> userList = userMapper.findAll();
// 6.输出结果
for(User user : userList) {
System.out.println(user);
}
}
@After
public void closeSqlSession() throws IOException {
// 7.释放资源
sqlSession.close();
inputStream.close();
}
}
2.4 MyBatis 运行原理
MyBatis 执行流程核心 8 步:

三、MyBatis 核心 CRUD 操作
3.1 查询操作
(1)单个参数查询
// DAO接口
public User findUserById(Integer id);
<!– Mapper配置 –>
<select id="findUserById" parameterType="java.lang.Integer" resultType="com.hg.pojo.User">
select * from user where id=#{id}
</select>
(2)多参数查询
方式 1:序号绑定
public User findUserByIdAndName(Integer id, String username);
<select id="findUserByIdAndName" resultType="com.hg.pojo.User">
SELECT * FROM user WHERE id = #{arg0} AND username = #{arg1}
<!– 或使用param1/param2:WHERE id = #{param1} AND username = #{param2} –>
</select>
方式 2:注解绑定
public User findUserByIdAndName2(@Param("id") Integer id, @Param("username")String username);
<select id="findUserByIdAndName2" resultType="com.hg.pojo.User">
SELECT * FROM user WHERE id = #{id} AND username = #{username}
</select>
方式 3:对象绑定
public User findUserByUserInfo(User user);
<select id="findUserByUserInfo" parameterType="com.hg.pojo.User" resultType="com.hg.pojo.User">
SELECT * FROM user WHERE id = #{id} AND username = #{username}
</select>
方式 4:Map 绑定
public User findUserByMap(Map<String, Object> map);
<select id="findUserByMap" parameterMap="java.util.Map" resultType="com.hg.pojo.User">
SELECT * FROM user WHERE id = #{id} AND username = #{username}
</select>
(3)模糊查询
public List<User> findUserByName(String username);
<select id="findUserByName" parameterType="string" resultType="com.hg.pojo.User">
<!– 推荐方式:防止SQL注入 –>
select * from user where username like concat('%',#{username},'%')
<!– 或:select * from user where username like '%${value}%' –>
</select>
(4)聚合函数查询
public Integer getTotal();
<select id="getTotal" resultType="int">
SELECT COUNT(id) FROM user
</select>
3.2 删除操作
public void deleteUserById(Integer id);
<delete id="deleteUserById" parameterType="Integer">
DELETE FROM user WHERE id = #{id}
</delete>
// 测试代码
@Test
public void testDeleteUserById(){
UserDao userDao = sqlSession.getMapper(UserDao.class);
userDao.deleteUserById(41);
sqlSession.commit(); // 手动提交事务
}
3.3 修改操作
public void updateUserById(User user);
<update id="updateUserById" parameterType="com.hg.pojo.User">
update user set username=#{username},password=#{password},
birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
@Test
public void testUpdateUserById(){
User userParam = new User();
userParam.setId(41);
userParam.setUsername("吴彦祖");
userParam.setSex("男");
userParam.setAddress("中国");
userParam.setBirthday(new Date());
userMapper.updateUserById(userParam);
}
3.4 新增操作(含主键回填)
public void insertUser(User user);
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id" parameterType="com.hg.pojo.User">
insert into user(username,password,birthday,sex,address)
values(#{username},#{password},#{birthday},#{sex},#{address})
</insert>
@Test
public void testInsertUser(){
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = new User();
user.setUsername("刘德华");
user.setPassword("111");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("香港");
userDao.insertUser(user);
System.out.println("新增记录的id值:"+user.getId()); // 获取自增主键
sqlSession.commit();
}
3.5 #{} vs ${} 核心区别
| 本质 | 预编译占位符 | SQL 字符串拼接 |
| 类型转换 | 自动 Java/JDBC 类型转换 | 无类型转换 |
| SQL 注入 | 可防止注入 | 存在注入风险 |
| 参数绑定 | 支持任意参数名(单个参数可写 value) | 单个参数只能写 value |
四、自定义 MyBatis(核心原理剖析)
4.1 核心设计模式
MyBatis 大量使用设计模式简化开发:
- 构建者模式:SqlSessionFactoryBuilder(屏蔽对象构建细节)
- 工厂模式:SqlSessionFactory(解耦 SqlSession 创建)
- 代理模式:SqlSession(创建 Mapper 代理对象)
4.2 核心对象封装
(1)配置类(Configuration)
public class Configuration {
private String driver;
private String url;
private String username;
private String password;
// 存储Mapper配置:key=namespace+id
private Map<String, MappedStatement> mappers = new HashMap<>();
// Getter & Setter
}
(2)SQL 封装类(MappedStatement)
public class MappedStatement {
private String queryString; // SQL语句
private String resultType; // 返回值类型
// Getter & Setter
}
(3)核心工具类
- Resources:加载配置文件
- XMLConfigBuilder:解析 XML 配置
- DataSourceUtil:获取数据库连接
- Executor:执行 SQL 并封装结果
五、原始 DAO 开发(了解)
5.1 DAO 实现类
public class UserDaoImpl implements UserDao {
private SqlSession sqlSession;
public UserDaoImpl(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> findAll() {
return sqlSession.selectList("com.hg.dao.UserDao.findAll");
}
@Override
public User findUserById(Integer id) {
return sqlSession.selectOne("com.hg.dao.UserDao.findUserById", id);
}
// 其他CRUD方法实现…
}
5.2 原始 DAO vs 代理 DAO 对比
| 代码量 | 需手动实现 DAO 类 | 仅需接口 + Mapper,自动生成代理 |
| 维护成本 | 高(SQL 与代码耦合) | 低(SQL 集中配置) |
| 开发效率 | 低 | 高 |
| 主流程度 | 几乎淘汰 | 目前主流 |
六、总结
MyBatis 作为轻量级持久层框架,核心优势在于:
掌握 MyBatis 核心原理,不仅能熟练使用框架,更能理解其设计思想,为解决复杂业务场景打下基础。
如果本文对你有帮助,记得收藏、点赞、关注~~~
网硕互联帮助中心




评论前必须登录!
注册