说明:这份文档完全跟着最开始的学习顺序整理,不跳步、不搞复杂术语,每一步都讲透,代码可以直接复制,遇到问题看"注意事项"就能解决,纯新手友好,不用怕看不懂。
一、先搞懂:MyBatis 核心基础(新手必看)
简单说:MyBatis 就是帮我们"偷懒"的工具,不用写复杂的数据库连接代码,我们写 Java 方法,它帮我们翻译成 SQL 语句,直接和数据库交互。
核心前提:我们已经有 3 个基础文件(后面会补全代码,先知道作用)
- Book.java(实体类):和数据库表(t_book)一一对应,存数据用;
- BookMapper.java(接口):写我们要做的操作(查、增、删、改),相当于"任务清单";
- BookMapper.xml(映射文件):写真正的 SQL 语句,把接口的方法翻译成数据库能懂的命令。
二、基础重点:参数传递(最容易错,先记牢)
接口方法有参数时,XML 里要通过 #{ } 取值,不同参数场景,写法不一样,记准下面4种,不用记原理,照着写就行。
1. 场景1:单个对象参数(最常用,比如传入一本书的信息)
核心规则:直接写 #{对象的属性名},MyBatis 会自动获取属性值(前提是实体类有 getter 方法)。
示例代码(对应接口+XML):
scss
// 1. BookMapper.java 接口(任务清单:根据 Book 对象查书)
Book selectOneBook2(Book book); // 参数是 Book 对象
xml
<!-- 2. BookMapper.xml 映射文件(翻译 SQL) -->
<select id="selectOneBook2" resultType="Book">
select * from t_book where name = #{name} and author = #{author
<!-- #{name} 就是 Book 对象的 name 属性,#{author} 是 author 属性 -->
</select>
2. 场景2:多个普通参数(比如传入 书籍名称+作者)
核心规则:用 #{param1}、#{param2} 取值,param1 对应接口第一个参数,param2 对应第二个参数,以此类推。
示例代码(对应接口+XML):
arduino
// 1. BookMapper.java 接口(任务清单:根据名称和作者查书)
Book selectOneBook(String name, String author); // 2个普通参数
xml
<!-- 2. BookMapper.xml 映射文件(翻译 SQL) -->
<select id="selectOneBook" resultType="Book">
select * from t_book where name = #{param1} and author = #{param2}
<!-- param1 = name,param2 = author -->
</select>
3. 场景3:多参数且含对象(比如传入 书籍名称+Book 对象)
核心规则:普通参数用 #{param1},对象参数用 #{paramN.属性名}(N 是参数顺序)。
示例代码(对应接口+XML):
arduino
// 1. BookMapper.java 接口(任务清单:名称+Book 对象查书)
Book selectOneBook3(String name, Book book); // 1个普通参数+1个对象参数
xml
<!-- 2. BookMapper.xml 映射文件(翻译 SQL) -->
<select id="selectOneBook3" resultType="Book">
select * from t_book where name = #{param1} and author = #{param2.author}
<!-- param1 = name,param2 = Book 对象,.author 是对象的属性 -->
</select>
4. 场景4:无参数(比如查询所有书籍)
核心规则:不用写 #{ },直接写 SQL 语句。
示例代码(对应接口+XML):
csharp
// 1. BookMapper.java 接口(任务清单:查所有书)
List<Book> selectAllBooks(); // 无参数,返回所有书的集合
xml
<!-- 2. BookMapper.xml 映射文件(翻译 SQL) -->
<select id="selectAllBooks" resultType="Book">
select * from t_book // 直接查所有数据
</select>
参数传递注意事项(必看!)
- 接口方法名 和 XML 里的 id 必须完全一样(比如接口是 selectOneBook,XML 里 id 也得是这个);
- 实体类 Book 必须有 getter 方法(MyBatis 靠它拿属性值),否则会报错;
- #{ } 里的属性名,必须和 Book 类的属性名一致(比如类里是 name,就不能写 bookName)。
三、核心操作:增删改查(从插入开始,逐个实现)
先补全 3 个基础文件的完整代码(直接复制,不用改),再逐个实现增删改查,每一步都有测试代码,复制就能运行。
第一步:补全 3 个基础文件(必做!)
1. 实体类:Book.java(存数据的"容器")
typescript
package com.msb.pojo;
public class Book {
// 对应数据库表 t_book 的 4 个字段:id(书的编号)、name(书名)、author(作者)、price(价格)
private Integer id;
private String name;
private String author;
private Double price;
// 必须写 getter/setter 方法(MyBatis 要靠它拿值、赋值)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getAuthor() { return author; }
public void setAuthor(String author) { this.author = author; }
public Double getPrice() { return price; }
public void setPrice(Double price) { this.price = price; }
}
2. 接口:BookMapper.java(所有操作的"任务清单")
java
package com.msb.mapper;
import com.msb.pojo.Book;
import java.util.List;
public interface BookMapper {
// 1. 查询操作(4种场景,前面讲过)
List<Book> selectAllBooks(); // 无参数,查所有
Book selectOneBook(String name, String author); // 多普通参数
Book selectOneBook2(Book book); // 单个对象参数
Book selectOneBook3(String name, Book book); // 多参数含对象
// 2. 插入操作(新增一本书)
int insertBook(Book book);
// 3. 删除操作(根据 id 删除一本书)
int deleteBookById(Integer id);
// 4. 修改操作(根据 id 修改书籍价格)
int updateBookPriceById(Integer id);
}
3. 映射文件:BookMapper.xml(翻译 SQL 的"工具")
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 必须写接口的全类名,和 BookMapper.java 对应 -->
<mapper namespace="com.msb.mapper.BookMapper">
<!-- 1. 查询所有书籍 -->
<select id="selectAllBooks" resultType="Book">
select * from t_book
</select>
<!-- 2. 多普通参数查询(名称+作者) -->
<select id="selectOneBook" resultType="Book">
select * from t_book where name = #{param1} and author = #{param2}
</select>
<!-- 3. 单个对象参数查询 -->
<select id="selectOneBook2" resultType="Book">
select * from t_book where name = #{name} and author = #{author}
</select>
<!-- 4. 多参数含对象查询 -->
<select id="selectOneBook3" resultType="Book">
select * from t_book where name = #{param1} and author = #{param2.author}
</select>
<!-- 5. 插入书籍 -->
<insert id="insertBook">
insert into t_book(id, name, author, price)
values(#{id}, #{name}, #{author}, #{price})
</insert>
<!-- 6. 根据 id 删除书籍 -->
<delete id="deleteBookById" parameterType="int">
delete from t_book where id = #{param1}
</delete>
<!-- 7. 根据 id 修改书籍价格(打半价) -->
<update id="updateBookPriceById" parameterType="int">
update t_book set price = price / 2 where id = #{param1}
</update>
</mapper>
4. 核心配置文件:mybatis.xml(MyBatis 启动必备)
作用:告诉 MyBatis 怎么连接数据库,复制后改 3 处自己的数据库信息(账号、密码、数据库名)。
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 给实体类起别名,后面 XML 里写 Book 不用写全类名 -->
<typeAliases>
<package name="com.msb.pojo"/>
</typeAliases>
<!-- 数据库连接配置(改下面3处!) -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- 改1:msb 是数据库名,改成自己的 -->
<property name="url" value="jdbc:mysql://localhost:3306/msb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/> <!-- 改2:自己的数据库账号(默认 root) -->
<property name="password" value="root"/> <!-- 改3:自己的数据库密码(默认 root) -->
</dataSource>
</environment>
</environments>
<!-- 告诉 MyBatis,映射文件在哪(不用改) -->
<mappers>
<mapper resource="mapper/BookMapper.xml"/>
</mappers>
</configuration>
第二步:逐个实现增删改查(带测试代码,直接复制运行)
所有测试代码都有固定模板,只改"调用接口方法"那一步,复制后右键运行即可,重点记"注意事项"。
1. 插入操作(新增一本书,最常用)
测试类:TestInsert.java(复制完整代码,直接运行)
java
package com.msb.test;
import com.msb.mapper.BookMapper;
import com.msb.pojo.Book;
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 java.io.InputStream;
public class TestInsert {
public static void main(String[] args) throws Exception {
// 固定模板,不用改
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
BookMapper mapper = sqlSession.getMapper(BookMapper.class);
// 核心:调用插入方法(改这里的书籍信息即可)
Book newBook = new Book();
newBook.setId(3); // 书的编号,不能和数据库里已有的重复
newBook.setName("红高粱"); // 书名
newBook.setAuthor("莫言"); // 作者
newBook.setPrice(46.7); // 价格
int count = mapper.insertBook(newBook); // 执行插入,返回受影响行数
// 判断是否插入成功
if (count > 0) {
System.out.println("插入成功!");
}
// 🔴 关键:插入必须提交事务,否则数据不会进数据库!
sqlSession.commit();
// 固定模板,不用改
sqlSession.close();
}
}
插入操作注意事项:
- id 不能重复(数据库里已有 id=1,就不能再设 id=1);
- 必须写 sqlSession.commit()(提交事务),否则控制台显示成功,数据库里没有数据;
- 返回值 count 是"受影响行数",插入1条就是1,0就是插入失败。
2. 删除操作(根据 id 删除一本书)
测试类:TestDelete.java(复制完整代码,直接运行)
ini
package com.msb.test;
import com.msb.mapper.BookMapper;
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 java.io.InputStream;
public class TestDelete {
public static void main(String[] args) throws Exception {
// 固定模板,不用改
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
BookMapper mapper = sqlSession.getMapper(BookMapper.class);
// 核心:调用删除方法(改这里的 id 即可,比如删除 id=1 的书)
int count = mapper.deleteBookById(1);
// 判断是否删除成功
if (count > 0) {
System.out.println("删除成功!");
} else {
System.out.println("删除失败(可能 id 不存在)!");
}
// 🔴 关键:删除必须提交事务!
sqlSession.commit();
// 固定模板,不用改
sqlSession.close();
}
}
删除操作注意事项:
- id 要存在(数据库里没有 id=10,删除 id=10 就会失败);
- 删除后数据无法恢复,谨慎操作;
- 同样要写 sqlSession.commit(),否则删除不生效。
3. 修改操作(根据 id 修改书籍价格)
测试类:TestUpdate.java(复制完整代码,直接运行)
ini
package com.msb.test;
import com.msb.mapper.BookMapper;
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 java.io.InputStream;
public class TestUpdate {
public static void main(String[] args) throws Exception {
// 固定模板,不用改
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
BookMapper mapper = sqlSession.getMapper(BookMapper.class);
// 核心:调用修改方法(改这里的 id 即可,比如修改 id=2 的书的价格)
int count = mapper.updateBookPriceById(2);
// 判断是否修改成功
if (count > 0) {
System.out.println("修改成功!");
} else {
System.out.println("修改失败(可能 id 不存在)!");
}
// 🔴 关键:修改必须提交事务!
sqlSession.commit();
// 固定模板,不用改
sqlSession.close();
}
}
修改操作注意事项:
- XML 里的 SQL 是"价格打半价"(price = price / 2),想改其他价格,直接改 SQL 即可;
- id 必须存在,否则修改失败;
- 提交事务不能少,否则修改不生效。
4. 查询操作(4种场景,测试代码通用)
测试类:TestSelect.java(复制后,根据需要调用对应方法)
ini
package com.msb.test;
import com.msb.mapper.BookMapper;
import com.msb.pojo.Book;
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 java.io.InputStream;
import java.util.List;
public class TestSelect {
public static void main(String[] args) throws Exception {
// 固定模板,不用改
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
BookMapper mapper = sqlSession.getMapper(BookMapper.class);
// 核心:调用查询方法(选一个即可,不用都写)
// 1. 查所有书籍
List<Book> bookList = mapper.selectAllBooks();
for (Book book : bookList) {
System.out.println("书名:" + book.getName() + ",作者:" + book.getAuthor());
}
// 2. 多普通参数查询(名称+作者)
// Book book1 = mapper.selectOneBook("项目驱动零起点学Java", "马士兵、赵珊珊");
// System.out.println("查询到的书:" + book1.getName());
// 3. 单个对象参数查询
// Book searchBook = new Book();
// searchBook.setName("红高粱");
// searchBook.setAuthor("莫言");
// Book book2 = mapper.selectOneBook2(searchBook);
// System.out.println("查询到的书:" + book2.getName());
// 4. 多参数含对象查询
// Book searchBook2 = new Book();
// searchBook2.setAuthor("莫言");
// Book book3 = mapper.selectOneBook3("红高粱", searchBook2);
// System.out.println("查询到的书:" + book3.getName());
// 🔴 重点:查询操作不用提交事务!
sqlSession.close(); // 直接关闭即可
}
}
查询操作注意事项:
- 查询不用提交事务,直接关闭会话即可;
- 查所有书籍返回的是 List 集合,需要用循环打印;
- 如果查询不到数据,会返回 null,不会报错。
四、新手常见报错 & 解决方法(必看!避坑)
遇到报错不用慌,对照下面的情况,直接找解决方法,99% 的问题都能解决。
| 常见报错 | 原因 | 解决方法 |
|---|---|---|
| 控制台显示成功,但数据库没有数据 | 增删改操作忘了提交事务(没写 sqlSession.commit()) | 在调用方法后,加上 sqlSession.commit() |
| NullPointerException(空指针) | Book 类没写 getter 方法,或传入的参数是 null | 补全 Book 类的 getter 方法;调用方法前给参数赋值(比如 newBook.setId(3)) |
| Invalid bound statement (not found) | 接口方法名和 XML 里的 id 不一致,或 namespace 写错 | 核对方法名和 id 完全一致;核对 namespace 是 com.msb.mapper.BookMapper |
| 无法连接数据库 | 数据库账号、密码、数据库名写错,或 MySQL 没启动 | 修改 mybatis.xml 里的3处数据库信息;启动 MySQL |
| There is no getter for property named 'name' | #{ } 里的属性名,和 Book 类的属性名不一致 | 修改 #{ } 里的内容,和 Book 类的属性名保持一致(比如类里是 name,就写 #{name}) |
五、总结(新手必记)
- 核心流程:写接口(任务清单)→ 写 XML(翻译 SQL)→ 写测试类(运行);
- 关键规则:接口方法名 = XML 的 id;增删改必须提交事务;查询不用;
- 参数取值:记准4种场景,直接照写,不用记原理;
- 避坑重点:别忘写 getter 方法、别忘提交事务、别写错接口和 XML 的对应关系。
这份文档完全跟着最开始的学习顺序整理,代码能直接复制,报错能快速解决,新手照着做,就能顺利完成 MyBatis 增删改查所有操作!