大家好,我是可乐。

上篇文章给大家撸了一遍用 JDBC 直接操作数据库的实例,还只是简单写了一个查询的接口,其代码量就已经很大了,并且可乐还给大家分析了直接使用 JDBC 带来的一些问题,总之是一种反人类的操作,为了让这种操作人类正常化,我们选择使用 ORM 框架。

本篇文章给大家从头搭建一遍,如何基于 XML 配置,使用 Mybatis 进行增删改查操作。

看到这,可能有读者就要问了,what?

#yyds干货盘点#mybatis源码解析2——实例搭建_mysql

我现在使用 Springboot 多爽,还要这些复杂的配置干啥?

可乐这里要说的是,Springboot 用起来是爽,它啥都给你封装好了,但是很多细节问题你可能并不知道,后续撸 Mybatis 的源码流程也是基于此,所以大家一定要过一遍 Mybatis 原始的执行方式。

项目源码地址:https://github.com/YSOcean/mybatisproject

这里可乐不会介绍各种配置含义,需要的可以直接参考官网,更加权威,你值得拥有:https://mybatis.org/mybatis-3/zh/configuration.html

1、创建库表

以 Mysql 数据库为例,表比较简单,这里可乐就直接放图和建表语句了。

-- ----------------------------
-- 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;

#yyds干货盘点#mybatis源码解析2——实例搭建_sql_02

2、创建工程

通过 IDEA 创建一个工程,并导入相应的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、创建与表对应的实体类对象

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、编写数据库配置文件 mybatis-config.xml

关于配置文件的详细介绍,可以参考官网: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>

<!-- 可以配置多个运行环境,但是每个 SqlSessionFactory 实例只能选择一个运行环境 -->
<!-- 默认使用的环境 ID,名字随意,但是要匹配下面其中一个环境 ID -->
<environments default="development">
<!-- 环境ID -->
<environment id="development">
<!--事务管理器
一、JDBC:这个配置直接简单使用了 JDBC 的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围
二、MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期
比如 spring 或 JEE 应用服务器的上下文,默认情况下,它会关闭连接。然而一些容器并不希望这样,
因此如果你需要从连接中停止它,就可以将 closeConnection 属性设置为 false,比如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
-->
<transactionManager type="JDBC"/>
<!--dataSource 元素使用标准的 JDBC 数据源接口来配置 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">


<!-- 根据 id 查询 person 表中的数据
id:唯一标识符,此文件中的id值不能重复
resultType:返回值类型,一条数据库记录也就对应实体类的一个对象
parameterType:参数类型,也就是查询条件的类型
-->
<select id="selectPersonById"
resultType="com.itcoke.bean.Person" parameterType="java.lang.Long" >
<!-- 这里和普通的sql 查询语句差不多,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着 -->
select * from person where pid = #{pid}
</select>



<!-- 根据 id 更新 person 表的数据 -->
<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 表插入一条数据 -->
<insert id="insertPerson" parameterType="com.itcoke.bean.Person">
insert into person(pname,page)
value(#{pname},#{page})
</insert>



<!-- 根据 id 删除 person 表的数据 -->
<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>

#yyds干货盘点#mybatis源码解析2——实例搭建_mybatis_03

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);

}

//根据id查询person表数据
@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";
//根据 sqlSessionFactory 产生 session
SqlSession sqlSession = sessionFactory.openSession();
Person person = sqlSession.selectOne(namespace + "." + method, 1L);
System.out.println(person);
sqlSession.close();
}


//根据id更新person表数据
@Test
public void testUpdatePersonById() {
String statement = "com.itcoke.mapper.PersonMapper.updatePersonById";
Person p = new Person();
p.setPid(2L);
p.setPage(18);
//根据 sqlSessionFactory 产生 session
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.update(statement, p);
sqlSession.commit();
sqlSession.close();
}


//向 person 表插入数据
@Test
public void testInsertPerson() {
String statement = "com.itcoke.mapper.PersonMapper.insertPerson";
Person p = new Person();
p.setPname("可乐");
p.setPage(18);
//根据 sqlSessionFactory 产生 session
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.insert(statement, p);
sqlSession.commit();
sqlSession.close();
}

//根据id更新person表数据
@Test
public void testDeletePersonById() {
String statement = "com.itcoke.mapper.PersonMapper.deletePersonById";
Person p = new Person();
p.setPid(4L);
//根据 sqlSessionFactory 产生 session
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.delete(statement, p);
sqlSession.commit();
sqlSession.close();
}
}


9、通过接口

在上面的例子中,我们发现 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);
}


②、测试

//根据id查询person表数据
//通过接口代理的方式
@Test
public void testInterfaceSelectPersonById() {
//根据 sqlSessionFactory 产生 session
SqlSession sqlSession = sessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
Person person = mapper.selectPersonById(1L);
System.out.println(person);
sqlSession.close();
}


8、小结

至此,我们从头到尾撸了一遍利用 Mybatis 进行增删改查,后面便会深入底层,梳理架构。