從0到1搭建Mybatis實例
大家好,我是可樂。
上篇文章給大家擼了一遍用 JDBC 直接操作數(shù)據(jù)庫的實例,還只是簡單寫了一個查詢的接口,其代碼量就已經(jīng)很大了,并且可樂還給大家分析了直接使用 JDBC 帶來的一些問題,總之是一種反人類的操作,為了讓這種操作人類正常化,我們選擇使用 ORM 框架。
本篇文章給大家從頭搭建一遍,如何基于 XML 配置,使用 Mybatis 進行增刪改查操作。
看到這,可能有讀者就要問了,what?

我現(xiàn)在使用 Springboot 多爽,還要這些復雜的配置干啥?
可樂這里要說的是,Springboot 用起來是爽,它啥都給你封裝好了,但是很多細節(jié)問題你可能并不知道,后續(xù)擼 Mybatis 的源碼流程也是基于此,所以大家一定要過一遍 Mybatis 原始的執(zhí)行方式。
項目源碼地址:https://github.com/YSOcean/mybatisproject
這里可樂不會介紹各種配置含義,需要的可以直接參考官網(wǎng),更加權威,你值得擁有:https://mybatis.org/mybatis-3/zh/configuration.html
1、創(chuàng)建庫表
以 Mysql 數(shù)據(jù)庫為例,表比較簡單,這里可樂就直接放圖和建表語句了。
-- ----------------------------
-- Table structure for person
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
`pid` int NOT NULL AUTO_INCREMENT,
`pname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`page` int DEFAULT NULL,
PRIMARY KEY (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of person
-- ----------------------------
BEGIN;
INSERT INTO `person` VALUES (1, 'itcoke', 11);
INSERT INTO `person` VALUES (2, 'IT可樂', 22);
COMMIT;

2、創(chuàng)建工程
通過 IDEA 創(chuàng)建一個工程,并導入相應的jar包。
以 maven 為例,配置 MySQL 和 Mybatis 即可。
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
整個項目結構可以參考我的GitHub地址:https://github.com/YSOcean/mybatisproject
3、創(chuàng)建與表對應的實體類對象
package com.itcoke.bean;
public class Person {
private Long pid;
private String pname;
private Integer page;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
@Override
public String toString() {
return "Person{" +
"pid=" + pid +
", pname='" + pname + '\'' +
", page=" + page +
'}';
}
}
4、編寫數(shù)據(jù)庫配置文件 mybatis-config.xml
關于配置文件的詳細介紹,可以參考官網(wǎng):https://mybatis.org/mybatis-3/zh/configuration.html
<?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>
<!-- 可以配置多個運行環(huán)境,但是每個 SqlSessionFactory 實例只能選擇一個運行環(huán)境 -->
<!-- 默認使用的環(huán)境 ID,名字隨意,但是要匹配下面其中一個環(huán)境 ID -->
<environments default="development">
<!-- 環(huán)境ID -->
<environment id="development">
<!--事務管理器
一、JDBC:這個配置直接簡單使用了 JDBC 的提交和回滾設置。它依賴于從數(shù)據(jù)源得到的連接來管理事務范圍
二、MANAGED:這個配置幾乎沒做什么。它從來不提交或回滾一個連接。而它會讓容器來管理事務的整個生命周期
比如 spring 或 JEE 應用服務器的上下文,默認情況下,它會關閉連接。然而一些容器并不希望這樣,
因此如果你需要從連接中停止它,就可以將 closeConnection 屬性設置為 false,比如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
-->
<transactionManager type="JDBC"/>
<!--dataSource 元素使用標準的 JDBC 數(shù)據(jù)源接口來配置 JDBC 連接對象源 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis-study"/>
<property name="username" value="root"/>
<property name="password" value="root1234"/>
</dataSource>
</environment>
</environments>
</configuration>
5、定義person表映射文件
官方權威地址:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html
<?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">
<mapper namespace="com.itcoke.mapper.PersonMapper">
<!-- 根據(jù) id 查詢 person 表中的數(shù)據(jù)
id:唯一標識符,此文件中的id值不能重復
resultType:返回值類型,一條數(shù)據(jù)庫記錄也就對應實體類的一個對象
parameterType:參數(shù)類型,也就是查詢條件的類型
-->
<select id="selectPersonById"
resultType="com.itcoke.bean.Person" parameterType="java.lang.Long" >
<!-- 這里和普通的sql 查詢語句差不多,后面的 #{id}表示占位符,里面不一定要寫id,寫啥都可以,但是不要空著 -->
select * from person where pid = #{pid}
</select>
<!-- 根據(jù) id 更新 person 表的數(shù)據(jù) -->
<update id="updatePersonById" parameterType="com.itcoke.bean.Person">
update person p
<trim prefix="set" suffixOverrides=",">
<if test="pname != null and pname != ''">
p.pname = #{pname},
</if>
<if test="page != null and page != ''">
p.page = #{page},
</if>
</trim>
where pid=#{pid}
</update>
<!-- 向 person 表插入一條數(shù)據(jù) -->
<insert id="insertPerson" parameterType="com.itcoke.bean.Person">
insert into person(pname,page)
value(#{pname},#{page})
</insert>
<!-- 根據(jù) id 刪除 person 表的數(shù)據(jù) -->
<delete id="deletePersonById" parameterType="Long">
delete from person where pid=#{pid}
</delete>
</mapper>
6、向 mybatis-config.xml 中注冊映射文件
<mappers>
<!-- 注冊PersonMapper.xml文件 -->
<mapper resource="com/itcoke/mapper/PersonMapper.xml"/>
</mappers>

7、編寫測試類
package com.itcoke;
import com.itcoke.bean.Person;
import com.itcoke.mapper.PersonMapper;
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.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MybatisprojectApplicationTests {
// 定義SqlSessionFactory
SqlSessionFactory sessionFactory = null;
@Before
public void init() {
//定義mybatis全局配置文件
String resource = "mybatis-config.xml";
//加載 mybatis 全局配置文件
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
//構建sqlSession的工廠
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
//根據(jù)id查詢person表數(shù)據(jù)
@Test
public void testSelectPersonById() {
/*這個字符串由 PersonMapper.xml 文件中 兩個部分構成
<mapper namespace="com.itcoke.mapper.PersonMapper"> 的 namespace 的值
<select id="selectPersonById" > id 值
*/
String namespace = "com.itcoke.mapper.PersonMapper";
String method = "selectPersonById";
//根據(jù) sqlSessionFactory 產(chǎn)生 session
SqlSession sqlSession = sessionFactory.openSession();
Person person = sqlSession.selectOne(namespace + "." + method, 1L);
System.out.println(person);
sqlSession.close();
}
//根據(jù)id更新person表數(shù)據(jù)
@Test
public void testUpdatePersonById() {
String statement = "com.itcoke.mapper.PersonMapper.updatePersonById";
Person p = new Person();
p.setPid(2L);
p.setPage(18);
//根據(jù) sqlSessionFactory 產(chǎn)生 session
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.update(statement, p);
sqlSession.commit();
sqlSession.close();
}
//向 person 表插入數(shù)據(jù)
@Test
public void testInsertPerson() {
String statement = "com.itcoke.mapper.PersonMapper.insertPerson";
Person p = new Person();
p.setPname("可樂");
p.setPage(18);
//根據(jù) sqlSessionFactory 產(chǎn)生 session
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.insert(statement, p);
sqlSession.commit();
sqlSession.close();
}
//根據(jù)id更新person表數(shù)據(jù)
@Test
public void testDeletePersonById() {
String statement = "com.itcoke.mapper.PersonMapper.deletePersonById";
Person p = new Person();
p.setPid(4L);
//根據(jù) sqlSessionFactory 產(chǎn)生 session
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.delete(statement, p);
sqlSession.commit();
sqlSession.close();
}
}
9、通過接口
在上面的例子中,我們發(fā)現(xiàn) statement 每次都要自己書寫拼接,很容易就寫錯了,這時候 MyBatis 提供了接口注冊方式。
①、在 mapper 包下面新建一個 PersonMapper 接口
注意要和 PersonMapper.xml 同名,且在同一個包下,因為要和 namespace 相同。
package com.itcoke.mapper;
import com.itcoke.bean.Person;
public interface PersonMapper {
Person selectPersonById(long pid);
void updatePersonById(Person person);
void insertPerson(Person person);
void deletePersonById(long pid);
}
②、測試
//根據(jù)id查詢person表數(shù)據(jù)
//通過接口代理的方式
@Test
public void testInterfaceSelectPersonById() {
//根據(jù) sqlSessionFactory 產(chǎn)生 session
SqlSession sqlSession = sessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
Person person = mapper.selectPersonById(1L);
System.out.println(person);
sqlSession.close();
}
8、小結
至此,我們從頭到尾擼了一遍利用 Mybatis 進行增刪改查,后面便會深入底層,梳理架構。
