Appearance
MyBatis 快速入门
从零开始搭建一个 MyBatis 项目,实现最简单的 CRUD 操作,体验 MyBatis 开发流程。
一、环境准备
技术栈:
JDK 8+
Maven 3.6+
MySQL 5.7+
MyBatis 3.5+1.1 数据库建表
sql
CREATE DATABASE mybatis_demo DEFAULT CHARACTER SET utf8mb4;
USE mybatis_demo;
CREATE TABLE `user` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` VARCHAR(50) NOT NULL COMMENT '用户名',
`age` INT COMMENT '年龄',
`email` VARCHAR(100) COMMENT '邮箱',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 插入测试数据
INSERT INTO `user` (name, age, email) VALUES
('张三', 25, 'zhangsan@test.com'),
('李四', 30, 'lisi@test.com'),
('王五', 28, 'wangwu@test.com');1.2 Maven 依赖
xml
<dependencies>
<!-- MyBatis 核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.15</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>二、全局配置文件
mybatis-config.xml(放在 src/main/resources 下):
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>
<!-- 属性配置(可引入外部 properties 文件) -->
<properties resource="db.properties"/>
<!-- 全局设置 -->
<settings>
<!-- 启用驼峰命名自动映射:user_name → userName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 打印 SQL 日志(使用 SLF4J) -->
<setting name="logImpl" value="SLF4J"/>
<!-- 延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
<!-- 类型别名 -->
<typeAliases>
<!-- 为 com.example.entity 包下所有类设置别名,即类名首字母小写 -->
<package name="com.example.entity"/>
</typeAliases>
<!-- 环境配置 -->
<environments default="development">
<environment id="development">
<!-- 事务管理器:JDBC 表示使用 JDBC 的事务管理 -->
<transactionManager type="JDBC"/>
<!-- 数据源:POOLED 表示使用 MyBatis 内置的连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 注册 Mapper 映射文件 -->
<mappers>
<!-- 方式一:逐个注册 XML -->
<!-- <mapper resource="mapper/UserMapper.xml"/> -->
<!-- 方式二:扫描包(推荐) -->
<package name="com.example.mapper"/>
</mappers>
</configuration>注意:
mappers中<package>扫描时,要求 XML 文件和接口在同一包路径下(resources 目录中要建相同的包结构)。
三、编写实体类与 Mapper
3.1 实体类
java
package com.example.entity;
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private Date createTime;
// 必须有无参构造器
public User() {}
// getter / setter(省略)
// toString()
}3.2 Mapper 接口
java
package com.example.mapper;
import com.example.entity.User;
public interface UserMapper {
User selectById(Long id);
List<User> selectAll();
int insert(User user);
int update(User user);
int deleteById(Long id);
List<User> selectByName(String name);
}3.3 Mapper XML
UserMapper.xml(放在 resources/com/example/mapper/ 下):
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.example.mapper.UserMapper">
<!-- 查询单个 -->
<select id="selectById" resultType="com.example.entity.User">
SELECT id, name, age, email, create_time
FROM user
WHERE id = #{id}
</select>
<!-- 查询全部 -->
<select id="selectAll" resultType="com.example.entity.User">
SELECT * FROM user
</select>
<!-- 新增(获取自增主键) -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (name, age, email)
VALUES (#{name}, #{age}, #{email})
</insert>
<!-- 修改 -->
<update id="update">
UPDATE user
SET name = #{name}, age = #{age}, email = #{email}
WHERE id = #{id}
</update>
<!-- 删除 -->
<delete id="deleteById">
DELETE FROM user WHERE id = #{id}
</delete>
<!-- 模糊查询 -->
<select id="selectByName" resultType="com.example.entity.User">
SELECT * FROM user
WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
</mapper>四、编写测试
java
package com.example;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
private UserMapper userMapper;
@Before
public void setUp() throws Exception {
// 1. 加载全局配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 2. 创建 SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3. 获取 SqlSession
sqlSession = sqlSessionFactory.openSession();
// 4. 获取 Mapper 代理对象
userMapper = sqlSession.getMapper(UserMapper.class);
}
@After
public void tearDown() {
if (sqlSession != null) {
sqlSession.close();
}
}
@Test
public void testSelectById() {
User user = userMapper.selectById(1L);
System.out.println(user);
}
@Test
public void testSelectAll() {
List<User> users = userMapper.selectAll();
users.forEach(System.out::println);
}
@Test
public void testInsert() {
User user = new User();
user.setName("赵六");
user.setAge(22);
user.setEmail("zhaoliu@test.com");
int rows = userMapper.insert(user);
System.out.println("插入成功,影响行数:" + rows);
System.out.println("自增主键:" + user.getId());
sqlSession.commit(); // 增删改必须提交!
}
@Test
public void testUpdate() {
User user = userMapper.selectById(1L);
user.setAge(26);
int rows = userMapper.update(user);
System.out.println("更新成功,影响行数:" + rows);
sqlSession.commit();
}
@Test
public void testDelete() {
int rows = userMapper.deleteById(4L);
System.out.println("删除成功,影响行数:" + rows);
sqlSession.commit();
}
@Test
public void testSelectByName() {
List<User> users = userMapper.selectByName("三");
users.forEach(System.out::println);
}
}五、开发流程总结
MyBatis 开发步骤(七步走):
① 建表 → 数据库建表
② 加依赖 → pom.xml 引入 mybatis + 驱动
③ 写配置 → mybatis-config.xml
④ 写实体 → Entity 类(POJO)
⑤ 写接口 → Mapper 接口
⑥ 写映射 → Mapper.xml(SQL 映射)
⑦ 写测试 → 获取 SqlSession → 执行操作
速记口诀:
表→依赖→配置→实体→接口→映射→测试六、关键注意事项
① 增删改必须手动提交事务
sqlSession.commit(); // 否则不会持久化到数据库
或者使用 openSession(true) 开启自动提交
② Mapper XML 必须和接口在同一路径
否则需要逐个配置 <mapper resource="..."/>
③ 实体类必须有 无参构造器
否则 MyBatis 反射创建对象时报错
④ #{ } 和 ${ } 的区别
#{} → 预编译占位符(防 SQL 注入)→ 推荐
${} → 字符串拼接(有 SQL 注入风险)→ 仅用于动态表名/列名
⑤ namespace 必须等于接口全限定名
否则无法绑定七、面试要点
| 问题 | 答案要点 |
|---|---|
| 开发步骤? | 建表→依赖→配置→实体→接口→映射→测试 |
| 增删改为什么需要 commit? | 默认手动提交,openSession() 不自动提交 |
| #{ } 和 ${ } 的区别? | #{} 预编译防注入,${} 字符串替换有风险 |
| 如何获取自增主键? | useGeneratedKeys="true" + keyProperty="id" |
