mybatis快速入门,参考mybatis官方文档:https://mybatis.net.cn/getting-started.html
一、快速入门
1、搭建环境,引入依赖
XML
<!-- mybatis的依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.17</version>
<scope>compile</scope>
</dependency>
<!-- 连接mysql数据库的依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>compile</scope>
</dependency>
2、创建mybatis的核心依赖mybatis-config.xml
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="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_study"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射文件-->
<mappers>
<mapper resource="mappers/BrandMapper.xml"/>
</mappers>
</configuration>
3、创建mapper接口
java
public interface BrandMapper {
/**
* mybatis面向接口编程的两个一致:
* 1、映射文件的namespace要和mapper接口的全类名保持一致
* 2、映射文件中sql语句的id要合mapper接口中的方法名一致
*/
/**
* 新增信息
*/
int insertBrand();
}
4、创建mabatis的映射文件
java
package com.doumi.mybatis.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Brand {
private Integer id;
private String brandName;
private String companyName;
private float price;
}
对应表的建表语句
sql
CREATE TABLE `tb_brand` (
`id` int NOT NULL AUTO_INCREMENT,
`brand_name` varchar(20) DEFAULT NULL,
`company_name` varchar(50) DEFAULT NULL,
`price` decimal(10,0) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
5、通过junit测试功能
java
public class MybatisTest {
@Test
public void testInsert() throws IOException {
/**
* 1、加载核心配置文件
*/
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
// SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession = sqlSessionFactory.openSession(true);//设置自动提交事务
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
int i = brandMapper.insertBrand();
System.out.println(i);
/**
* 默认使用jdbc的事务管理器,需要手动提交事务
* 如果需要自动提交事务,需要openSession的时候添加一个参数
* SqlSession sqlSession = sqlSessionFactory.openSession(true);//设置自动提交事务
*
*/
// sqlSession.commit();
sqlSession.close();
}
}
6、加入log4j日志功能
加入log4依赖及log4j.xml的配置
XML
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://logging.apache.org/xml/ns"
xsi:schemaLocation="
https://logging.apache.org/xml/ns
https://logging.apache.org/xml/ns/log4j-config-2.xsd">
<Appenders>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<Console name="CONSOLE">
<JsonTemplateLayout/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.doumi.mybatis" level="DEBUG" >
<appender-ref ref="STDOUT"/>
</Logger>
<Logger name="org.apache.ibatis" level="DEBUG" >
<appender-ref ref="STDOUT"/>
</Logger>
<Root level="DEBUG">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
二、mybatis核心配置文件
1、核心配置文件mybatis-config.xml
其中的标签需要按照顺序写,否则会报错
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>
<setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>
</settings>
<!-- 类型别名,可以使用别名来表示类名
typeAlias:设置某个类型的别名
type:设置需要设置别名的类名
alias:设置某个类型的别名,如果不设置该属性,那么该类型拥有默认的别名,即类名且不区分大小写
-->
<typeAliases>
<typeAlias type="com.doumi.mybatis.pojo.Brand" alias=""></typeAlias>
</typeAliases>
<!--
environments:配置多个连接数据库的环境
environment 属性:
id:表示连接数据库的环境的唯一标识,不能重复
transactionManager:
type="JDBC|MANAGED"
JDBC:表示当前环境,执行sql时使用的是JDBC中原生的事务管理方式,事务的提交需要手动提交
MANAGED:被管理,例如spring
-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--
dataSource:配置数据源
属性:
type:设置数据源的类型
type="POOLED|UNPOOLED|JNDI"
POOLED:比哦啊是使用数据库连接池缓存数据库连接
UNPOOLED:表示不使用数据库连接池
JNDI:表示使用上下文中的数据源
-->
<dataSource type="POOLED">
<!-- 设置连接数据库的驱动 -->
<property name="driver" value="${jdbc.driver}"/>
<!-- 设置连接数据库的地址 -->
<property name="url" value="${jdbc.url}"/>
<!-- 设置连接数据库的用户名 -->
<property name="username" value="${jdbc.username}"/>
<!-- 设置连接数据库的密码 -->
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射文件-->
<mappers>
<!-- 引入单个映射文件-->
<!-- <mapper resource="mappers/BrandMapper.xml"/>-->
<!-- 以包为单位引入映射文件
要求:
1、mapper接口所在的包要和映射文件所在的包一致
2、mapper接口要和映射文件的名字一致
-->
<package name="com.doumi.mybatis.mapper"/>
</mappers>
</configuration>
2、在idea中设置mybatis-config的模版
1、在idea的settings中,添加模版:

模版内容如下
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"/>
<!-- 定义类型别名-->
<typeAliases>
<package name=""/>
</typeAliases>
<!-- 环境定义-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 定义mapper信息-->
<mappers>
<package name=""/>
</mappers>
</configuration>
新建一个mybatis-config.xml类型的文件,直接输入文件名,不需要输入后缀名,即可得到和模版一样的文件,只需按需要修改即可


三、mybatis获取参数值的方式
获取参数值的两种方式:
${}:本质是字符串拼接,需要手动加单引号
#{}:本质是占位符
1、mapper接口方法的参数是单个的字面量类型
可以通过{}和#{}以任意的名称,获取参数数值,但是需要注意{}需要手动加单引号

2、mapper接口方法的参数为多个时
此时mybatis会讲这些参数封装在一个map集合中,以两种方式进行存储
1》以 arg0 、rag1为键,以参数为值
2》以param0、param1为键,以参数为值
因此,只需要通过#{}和{}以键的方式访问值即可,但是需要注意{}的单引号问题


3、若mapper接口方法的参数有多个时,可以手动将这些参数放在一个map中存储
只需要通过#{}和{}以键的方式访问值即可,但是需要注意{}的单引号问题

4、mapper中接口方法的参数是实体类对象的时
只需要通过#{}和${}以属性名进行访问值即可

5、命名参数注解@Param("参数名")
1》以@Param注解的值( 即参数名1 、参数名2 )为键,以参数为值
2》以param0、param1为键,以参数为值
因此,只需要通过#{}和{}以键的方式访问值即可,但是需要注意{}的单引号问题



四、mybatis各种查询功能
1、查询一个实体类对象

2、查询一个list集合

3、查询单个数据

4、查询一条数据为一个map集合

5、查询多条数据为一个map集合
方式一:

方式二:

五、特殊sql的执行
1、模糊查询

2、批量删除

3、动态设置表名

4、添加功能,获取自增主键

六、自动映射
1、resultMap处理字段和属性的映射关系
解决字段名和属性名不一致的情况:
1)给字段起别名,保持和属性名一致

2)设置全局配置,将自动映射为驼峰


3)通过ResultMap设置自定义的映射关系




2、多对一映射处理
2.1 级联属性赋值


2.2 使用association



2.3 分步查询




resultMap设置:

分步查询中,关于延迟加载的说明

设置开启延迟加载:

setting中的延迟加载是全局设置。
设置延迟加载后,如果只查询第一步中的字段,则第二个sql不会被执行。
如果有特殊情况,需要把所有信息都查出来,可以在association中通过fetchType=eager进行设置,那么两个sql都将被执行,如下:

3、一对多映射
3.1 collection





3.2 分步查询





七、动态sql
1、if


2、where

3、trim


4、choose、when、otherwise



5、foreach

批量删除

写法二:

批量添加

6、sql标签


八、mybatis的缓存
1、一级缓存
SqlSession级别的,默认开启

java
package com.doumi.mybatis;
import com.doumi.mybatis.mapper.CacheMapper;
import com.doumi.mybatis.mapper.EmpMapper;
import com.doumi.mybatis.pojo.Emp;
import com.doumi.mybatis.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.io.IOException;
public class CacheMapperTest {
/**
* 一级缓存生效
* 测试一级缓存
* 一级缓存是sqlSession级别的,通过同一个sqlSession查询的数据将被缓存,下次查询相同的数据,将会从缓存获取,不会重新查询数据库
* @throws IOException
*/
@Test
public void TestLevelOneCache() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession();
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
System.out.println(mapper.getEmpById(1));
sqlSession.close();
}
/**
* 一级缓存生效
* @throws IOException
*/
@Test
public void TestLevelOneCache2() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession();
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
CacheMapper mapper2 = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper2.getEmpById(1));
sqlSession.close();
}
/**
* -------------------以下是一级缓存失效的四种情况----------------------------------------------------------------------
* 一级缓存失效的四种情况
* 1、不同的sqlSession
* 2、不同的查询条件
* 3、两次查询中有任意增删改操作
* 4、两次查询之间进行了手动清除缓存
* @throws IOException
*/
/**
* 1、不同的sqlSession
* @throws IOException
*/
@Test
public void TestLevelOneCacheFail1() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession();
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
SqlSession sqlSession2 = MybatisUtils.getSqlSessionFactory().openSession();
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
System.out.println(mapper2.getEmpById(1));
sqlSession.close();
}
/**
* 2、不同的查询条件
* @throws IOException
*/
@Test
public void TestLevelOneCacheFail2() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession();
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
System.out.println(mapper.getEmpById(2));
sqlSession.close();
}
/**
* 3、两次查询中有任意增删改操作
* @throws IOException
*/
@Test
public void TestLevelOneCacheFail3() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession(true);
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
mapper.insertEmp(new Emp(null, "张三", 23, "男", 2));
System.out.println(mapper.getEmpById(1));
sqlSession.close();
}
/**
* 4、手动清除缓存
* @throws IOException
*/
@Test
public void TestLevelOneCacheFail4() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession(true);
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
sqlSession.clearCache();
System.out.println(mapper.getEmpById(1));
sqlSession.close();
}
}
2、二级缓存

java
package com.doumi.mybatis;
import com.doumi.mybatis.mapper.CacheMapper;
import com.doumi.mybatis.pojo.Emp;
import com.doumi.mybatis.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.io.IOException;
public class CacheTwoTest {
/**
* 二级缓存
* 二级缓存是sqlSessionFactory级别的,通过同一个sqlSessionFactory创建的sqlSession查询的结果会被缓存。
* 此后若再次执行相同的查询语句,结果就会从缓存中获取
*
* 二级缓存开启的条件
* 1、核心配置文件settings配置参数cacheEnabled=true,默认就是true,缓存开启
* <setting name="cacheEnabled" value="true"/>
* 2、mapper中添加标签<cache>
* 3、二级缓存必须在sqlSession提交或关闭后有效
* 4、查询的数据转换的实体类必须实现Serializable接口
*
* 二级缓存失效的情况:
* 两次查询之间有增删改操作,是一二级缓存同时失效
*
* @throws IOException
*/
@Test
public void TestLevelTwoCache() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession();
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
sqlSession.close();//必须关闭第一个sqlSession结果数据才能放入二级缓存,负责不能被放入缓存
SqlSession sqlSession2 = MybatisUtils.getSqlSessionFactory().openSession();
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
System.out.println(mapper2.getEmpById(1));
sqlSession2.close();
}
/**
* 二级缓存失效
* 两次查询之间有增删改操作
* @throws IOException
*/
@Test
public void TestLevelTwoCacheFail() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession(true);
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
System.out.println(mapper.getEmpById(1));
sqlSession.close();
SqlSession sqlSession2 = MybatisUtils.getSqlSessionFactory().openSession(true);
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
mapper2.insertEmp(new Emp(null,"二级缓存失效",23,"男",2));
sqlSession2.close();
SqlSession sqlSession3 = MybatisUtils.getSqlSessionFactory().openSession(true);
CacheMapper mapper3 = sqlSession3.getMapper(CacheMapper.class);
System.out.println(mapper3.getEmpById(1));
sqlSession3.close();
}
}
3、二级缓存的相关配置

4、Mybatis缓存的查询顺序

5、整合第三方缓存EHCache
1、添加依赖

2、各jar包功能

3、创建ehcache的配置文件ehcache.xml

4、设置二级缓存

5、加入logback日志


6、EHCache配置文件说明


九、MyBatis的逆向工程

1、添加maven依赖
在项目的 pom.xml 中,你需要添加 MyBatis Generator 的 Maven 插件以及数据库驱动依赖。
XML
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.2</version> <!-- 推荐使用较新版本 -->
<configuration>
<overwrite>true</overwrite> <!-- 允许覆盖已生成的文件 -->
<verbose>true</verbose> <!-- 打印详细日志 -->
</configuration>
<dependencies>
<!-- 必须包含数据库驱动依赖,否则插件无法连接数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
2、创建逆向工程的文件generatorConfig.xml
在 src/main/resources 目录下创建 generatorConfig.xml。这是逆向工程的"大脑",控制着生成什么代码以及生成在哪里。

XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 上下文配置 -->
<context id="MysqlContext" targetRuntime="MyBatis3">
<!-- 1. 注释生成器配置 -->
<commentGenerator>
<!-- 是否去除注释 -->
<property name="suppressAllComments" value="false"/>
<!-- 是否去除生成的日期 -->
<property name="suppressDate" value="true"/>
</commentGenerator>
<!-- 2. 数据库连接配置 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_study?useSSL=false&serverTimezone=UTC"
userId="root"
password="root123456">
</jdbcConnection>
<!-- 3. 生成 Java 实体类的位置 -->
<javaModelGenerator targetPackage="com.doumi.mybatis.pojo" targetProject="src/main/java">
<!-- 是否在包下生成子包 -->
<property name="enableSubPackages" value="true"/>
<!-- 是否对字符串字段调用 trim -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 4. 生成 Mapper XML 文件的位置 -->
<sqlMapGenerator targetPackage="com.doumi.mybatis.mapper" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 5. 生成 Mapper 接口的位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.doumi.mybatis.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 6. 指定要生成的表 -->
<!-- tableName: 数据库表名 -->
<!-- domainObjectName: 生成的 Java 类名 -->
<table tableName="emp" domainObjectName="Emp" enableCountByExample="false" enableUpdateByExample="false"/>
<table tableName="dept" domainObjectName="Dept" enableCountByExample="false" enableUpdateByExample="false"/>
<table tableName="tb_brand" domainObjectName="Brand" enableCountByExample="false" enableUpdateByExample="false"/>
</context>
</generatorConfiguration>
3、执行生成命令
配置完成后,在 Maven 项目面板中找到 mybatis-generator 插件,双击运行 mybatis-generator:generate 目标。或者在命令行执行:
bash
mvn mybatis-generator:generate
十、分页插件
1、分页插件使用步骤
1>、添加依赖

2>、配置分页插件

2、分页插件的使用

java
package com.doumi.mybatis;
import com.doumi.mybatis.mapper.DeptMapper;
import com.doumi.mybatis.mapper.EmpMapper;
import com.doumi.mybatis.pojo.Dept;
import com.doumi.mybatis.utils.MybatisUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
public class PageHelperTest {
/**
* limit index pageSize
* index:当前页的起始索引
* pageSize:每页显示的条数
* pageNum:当前页的页码
* index = (pageNum-1)* pageSize
*
* 使用Mybatis的分页插件实现分页功能:
* 1、需要在查询功能之前开启分页
* PageHelper.startPage(int pageNum, int pageSize);
* 2、在查询功能之后获取分页相关信息
* PageInfo<Dept> pageInfo = new PageInfo<>(list,3);
* list 表示分页数据
* 3:表示当前导航分页的数量
*/
@Test
public void testPageHelper() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Page<Object> page = PageHelper.startPage(1, 3);
mapper.selectByExample(null);
System.out.println(page);
sqlSession.close();
}
/**
* 导航栏
* @throws IOException
*/
@Test
public void testPageHelperNavigator() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
PageHelper.startPage(4, 3);
List<Dept> list = mapper.selectByExample(null);
PageInfo<Dept> pageInfo = new PageInfo<>(list,3);
System.out.println(pageInfo);
sqlSession.close();
}
}