0%

实习日志-工具框架-MybatisPlus

undefined

Mybatis & MybatisPlus

MybatisPlus简称MP,是对Mybatis的增强,通过在其基础上的进一步封装来进一步简化开发,由国人开发。官网,其分2.x3.x两个大版本,本文以2.3版本为例介绍其的使用-> 参考文档

学习视频:链接: https://pan.baidu.com/s/1Whu0pBMIvNJ5FsEArI6YLQ 提取码: dp40

初体验

环境准备

创建测试表

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE tbl_employee(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(50),
email VARCHAR(50),
gender CHAR(1),
age int
);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom','tom@atguigu.com',1,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Jerry','jerry@atguigu.com',0,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Black','black@atguigu.com',1,30);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('White','white@atguigu.com',0,35);

创建maven工程,添加依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
<!--junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>

创建实体类

1
2
3
4
5
6
7
8
9
10
@Data
public class Employee {

private Integer id;
private String lastName;
private String email;
private Integer gender;
private Integer age;

}

创建log4j配置文件log4j.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd
HH:mm:ss,SSS} %m (%F:%L) \n"/>
</layout>
</appender>
<logger name="java.sql">
<level value="debug"/>
</logger>
<logger name="org.apache.ibatis">
<level value="info"/>
</logger>
<root>
<level value="debug"/>
<appender-ref ref="STDOUT"/>
</root>
</log4j:configuration>

创建spring配置文件applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">


<!-- 数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 事务管理器 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 基于注解的事务管理 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

<!-- 配置 SqlSessionFactoryBean -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 别名处理 -->
<property name="typeAliasesPackage" value="cn.tuhu.mp.entity"></property>
</bean>
<!--
配置 mybatis 扫描 mapper 接口的路径
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.tuhu.mp.mapper"></property>
</bean>
</beans>

使用Mybatis实现查询

原来我们在spring集成mybatis之后,需要编写XxxMapper接口和方法,并在该类所在包路径下编写同名的XxxMapper.xmlnamespace为对应接口的全限定名,sql标签的id与接口中对应方法名一致,标签内写sql语句):

EmployeeMapper.java

1
2
3
4
5
6
7
8
9
package cn.tuhu.mp.mapper;

import cn.tuhu.mp.entity.Employee;
import java.util.List;

public interface EmployeeMapper {

List<Employee> findAll();
}

src/main/resources/cn/tuhu/mp/mapper/EmployeeMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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="cn.tuhu.mp.mapper.EmployeeMapper">
<resultMap id="BaseResultMap" type="cn.tuhu.mp.entity.Employee">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<result column="age" property="age"/>
</resultMap>
<select id="findAll" parameterType="int" resultMap="BaseResultMap">
select * from tbl_employee
</select>
</mapper>

注意:如果你使用的IDE是IDEA,这里有个坑,右键resources->New->Directory,应该写cn/tuhu/mp/mapper,这样才会创建级联文件夹,如果你写cn.tuhu.mp.mapper则会将其整个作为一个名称创建一个文件夹,这会导致编译后EmployeeMapper.xml无法和EmployeeMapper.java处于同一个目录下。

还有一个大坑就是,如果选择的是右键->New->File的方式创建EmployeeMapper.xml,那么文件名一定要带.xml扩展名后缀,切不可只写EmployeeMapper然后再根据编辑文件类型提示选择xml(这样也许在IDEA中能够正常显示xml标签,但是框架只严格扫描扩展名为xml的映射文件,这回导致明明你反复检查,确认了xml中的namespace和接口全限定名一致,sql标签的id与接口中定义的方法名一致,却仍然抛出Invalid bound statement (not found): com.mapper.EmployeeMapper.findAll的异常)。

EmployeeMapperTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.tuhu.mp.mapper;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class EmployeeMapperTest {

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

@Test
public void testFindAll() {
EmployeeMapper employeeMapper = context.getBean(EmployeeMapper.class);
System.out.println(employeeMapper.findAll());
}
}

集成MybatisPlus

再新建一个maven项目,复制之前的依赖,将mybatismybatis-spring去掉,添加mybatis-plus即可(因为mybatis-plus自身依赖了mybatismybatis-spring

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.3</version>
</dependency>

然后将applicationContext.xml中的org.mybatis.spring.SqlSessionFactoryBean替换成com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean即可,如此就在集成了Mybatis的基础上,进一步集成了MybatisPlus

1
2
3
4
5
6
<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 别名处理 -->
<property name="typeAliasesPackage" value="cn.tuhu.mp.entity"></property>
</bean>

我们不在需要编写接口及CURD方法和其对应的映射文件了,我们只需创建一个空的EmployeeMapper接口继承BaseMapper即可调用针对Employee实体类的通用CURD操作了。

1
2
3
4
5
6
7
8
package cn.tuhu.mp.mapper;

import cn.tuhu.mp.entity.Employee;
import com.baomidou.mybatisplus.mapper.BaseMapper;

public interface EmployeeMapper extends BaseMapper<Employee> {

}

由于MP是将实体类名首字母小写作为表名,属性名作为字段名为我们生成SQL的,因此不同之处我们还需声明一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package cn.tuhu.mp.entity;

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;

@Data
@TableName(value = "tbl_employee")
public class Employee {

@TableId(type = IdType.AUTO) //mysql主键生成策略:自增
Integer id;
@TableField(value = "last_name")
String lastName;
String email;
Integer gender;
Integer age;

}

如此便可测试了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.tuhu.mp.mapper;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class EmployeeMapperTest {

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

@Test
public void testFindAll() {
EmployeeMapper employeeMapper = context.getBean(EmployeeMapper.class);
System.out.println(employeeMapper.selectById(1));
}
}

原理

我们压根就没写DAO方法和对应的SQL语句,MP是如何做到帮助我们生产对应的代理DAO对象的呢?既然我们通过继承BaseMapper就省去了原来DAO方法和SQL映射的书写,那么密码肯定就在BaseMapper中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* <p>
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
* </p>
* <p>
* 这个 Mapper 支持 id 泛型
* </p>
*
* @author hubin
* @Date 2016-01-23
*/
public interface BaseMapper<T> {

/**
* <p>
* 插入一条记录
* </p>
*
* @param entity 实体对象
* @return int
*/
Integer insert(T entity);

...

}

可以看到此类中封装了大量通用CURD操作,并将操作的具体实体类作为泛型参数以实现复用。

也就是说我们的EmployeeMapper继承BaseMapper之后,就通过传递的泛型继承了定义在其中的针对Employee的通用CRUD操作。

而我们在applicationContext.xml中替换SqlSessionFactoryBeanMybatisSqlSessionFactoryBean之后,MybatisPlus就会在原有Mybatis扫描mapper包下接口及同名SQL映射的方式生成绑定(一个DAO方法对应一个SQL)的基础上,为继承了BaseMapper的接口生成一系列的通用CRUD SQL缓存在mappedStatements中(keyBaseMapper中的各个方法,value为方法对应的SQL信息)。

收尾

CURD查询、AR查询、代码生成器、插件扩展等用法见 参考文档

IDEA插件MybatisX,可以帮助我们在编写DAO方法后alt + insert在对应的映射文件中生成SQL标签,还可以帮助我们在javaxml之间来回跳转。

鼓励一下~