为了方便测试,我们先创建一个新的项目,并准备一些基础数据。
导入项目
注意配置一下项目的JDK版本为JDK11。首先点击项目结构设置:
导入两张表,在课前资料中已经提供了SQL
文件:
最后,在application.yaml
中修改jdbc
参数为你自己的数据库参数:
比如我们要实现User
表的CRUD
,只需要下面几步:
MybatisPlus
依赖Mapper
MybatisPlus
提供了starter
,实现了自动Mybatis
以及MybatisPlus
的自动装配功能,坐标如下:
SpringBoot自动装配是指SpringBoot会自动将一些配置类的bean注册到IOC容器中,我们可以在需要的地方使用@Autowired或@Resource等注解来使用它。SpringBoot定义了一套接口规范,这套规范规定:SpringBoot在启动时会扫描外部引用jar包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到Spring容器并执行类中定义的各种操作。自动装配可以简单理解为:通过注解或者一些简单的配置就能在SpringBoot的帮助下实现某块功能。这样就可以更快速地构建应用程序,而无需手动配置大量的bean。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
由于这个starter
包含对mybatis
的自动装配,因此完全可以替换掉Mybatis
的starter
。
最终,项目的依赖如下:
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
为了简化单表CRUD
,MybatisPlus
提供了一个基础的BaseMapper
接口,其中已经实现了单表的CRUD
:
因此我们自定义的Mapper
只要实现了这个BaseMapper
,就无需自己实现单表CRUD
了。
修改mp-demo
中的com.itheima.mp.mappe
r包下的UserMapper
接口,让其继承BaseMapper
:
代码如下:
package com.itheima.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
public interface UserMapper extends BaseMapper<User> {
}
新建一个测试类,编写几个单元测试,测试基本的CRUD
功能:
package com.itheima.mp.mapper;
import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.List;
@SpringBootTest
class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
void testInsert() {
User user = new User();
user.setId(5L);
user.setUsername("Lucy");
user.setPassword("123");
user.setPhone("18688990011");
user.setBalance(200);
user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userMapper.insert(user);
}
@Test
void testSelectById() {
User user = userMapper.selectById(5L);
System.out.println("user = " + user);
}
@Test
void testSelectByIds() {
List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L, 5L));
users.forEach(System.out::println);
}
@Test
void testUpdateById() {
User user = new User();
user.setId(5L);
user.setBalance(20000);
userMapper.updateById(user);
}
@Test
void testDelete() {
userMapper.deleteById(5L);
}
}
可以看到,在运行过程中打印出的SQL
日志,非常标准:
11:05:01 INFO 15524 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
11:05:02 INFO 15524 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : ==> Preparing: SELECT id,username,password,phone,info,status,balance,create_time,update_time FROM user WHERE id=?
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : ==> Parameters: 5(Long)
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : <== Total: 1
user = User(id=5, username=Lucy, password=123, phone=18688990011, info={"age": 21}, status=1, balance=20000, createTime=Fri Jun 30 11:02:30 CST 2023, updateTime=Fri Jun 30 11:02:30 CST 2023)
只需要继承BaseMapper
就能省去所有的单表CRUD
,是不是非常简单!
在刚刚的入门案例中,我们仅仅引入了依赖,继承了BaseMapper
就能使用MybatisPlus
,非常简单。但是问题来了:
MybatisPlus
如何知道我们要查询的是哪张表?表中有哪些字段呢?
大家回忆一下,UserMapper
在继承BaseMapper
的时候指定了一个泛型:
泛型中的User
就是与数据库对应的PO
.
MybatisPlus
就是根据PO
实体的信息来推断出表的信息,从而生成SQL
的。默认情况下:
MybatisPlus
会把PO
实体的类名驼峰转下划线作为表名:例如:类名为userInfo
==> user_info
MybatisPlus
会把PO
实体的所有变量名驼峰转下划线作为表的字段名,并根据变量类型推断字段类型 类字段名createTime
==>表的字段名 create_time
MybatisPlus
会把名为id
的字段作为主键MybatisPlus
提供了一些注解便于我们声明表信息。说明:
- 描述:表名注解,标识实体类对应的表
- 使用位置:实体类
示例:
@TableName("user")
public class User {
private Long id;
private String name;
}
TableName
注解除了指定表名以外,还可以指定很多其它属性:
说明:
- 描述:主键注解,标识实体类中的主键字段
- 使用位置:实体类的主键字段
示例:
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
}
TableId
注解支持两个属性:
这里比较常见的有三种:
AUTO
:利用数据库的id自增长INPUT
:手动生成idASSIGN_ID
:雪花算法生成Long类型的全局唯一id,这是默认的ID
策略(mybatisPlus
默认是雪花算法作为id
策略)说明:
描述:普通字段注解
示例:
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
private Integer age;
@TableField("isMarried")
private Boolean isMarried;
@TableField("`concat`")
private String concat;
}
一般情况下我们并不需要给字段添加@TableField
注解,一些特殊情况除外:
isXXX
命名,按照JavaBean
的规范,MybatisPlus
识别字段时会把is
去除,这就导致与数据库不符。@TableField
注解给字段名添加转义字符: ``如下图中,order
与数据库关键字冲突 必须使用 `` 进行标识
支持的其它属性,看mybatisplus
官网:
https://baomidou.com/pages/223848/#idtype
MybatisPlus
也支持基于yaml
文件的自定义配置,详见官方文档:
https://www.baomidou.com/pages/56bac0/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
大多数的配置都有默认值,因此我们都无需配置。但还有一些是没有默认值的,例如:
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po
global-config:
db-config:
id-type: auto # 全局id类型为自增长
需要注意的是,MyBatisPlus
也支持手写SQL
的,而mapper
文件的读取地址可以自己配置:
mybatis-plus:
mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,当前这个是默认值。
可以看到默认值是classpath*:/mapper/**/*.xml
,也就是说我们只要把mapper.xml
文件放置这个mapper
目录下就一定会被加载。
例如,我们新建一个UserMapper.xml
文件,然后在其中定义一个方法:
然后在测试类UserMapperTest
中测试该方法:
@Test
void testQuery() {
User user = userMapper.queryById(1L);
System.out.println("user = " + user);
}