Mybatis Plus之内置Mapper实践
MyBatis Plus,作为对MyBatis的进一步增强,大大简化了我们的开发流程,提高了开发速度
配置
由于Mybatis Plus是建立在Mybatis之上的,所以其已经依赖了Mybatis,故我们无需在项目中显式地重复添加Mybatis依赖。直接在POM文件中Mybatis Plus依赖即可
<!--Mybatis Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
Mapper CRUD操作
在Mybatis下,需要我们自行编写Mapper接口文件、提供sql的的xml文件。众所周知,这些CRUD的接口写起来不仅繁琐还容易出错,为此在Mybatis Plus中提供了内置的Mapper。高效实现CRUD操作
-- 创建数据表
create table t_people_info (
id int not null auto_increment comment 'ID',
name varchar(255) null comment '姓名',
sex varchar(255) null comment '性别',
primary key (id)
) comment '信息表';
POJO类定义如下,这里展示了@TableName、@TableField注解的用法
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_people_info") // 指定数据库的表名
public class People {
/**
* ID
*/
private int id;
/**
* 姓名
*/
@TableField("name") // 该属性在数据表中对应的字段名
private String username;
/**
* 性别
*/
private String sex;
/**
* 职业
*/
@TableField(exist = false) // 该属性在数据表中不存在
private String job;
}
而Mapper接口文件只需继承BaseMapper即可获得Mybatis Plus提供的基本的CRUD功能,无需我们定义接口及相关的SQL。当然如果需要复杂的操作直接在PeopleMapper接口中继续添加即可
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface PeopleMapper extends BaseMapper<People> {
}
增
public class ProperService {
@Autowired
private PeopleMapper peopleMapper;
public void testInsert() {
List<People> list = new LinkedList<>();
list.add( People.builder().username("小明").build() );
list.add( People.builder().id(10).username("老王").sex("男").build() );
list.add( People.builder().id(11).username("老张").sex("女").build() );
list.add( People.builder().id(12).sex("女").build() );
for (People people : list) {
peopleMapper.insert(people);
}
}
}
删
根据ID删除及批量操作,方式如下
/**
* 根据ID删除
*/
public void testDeleteById() {
peopleMapper.deleteById(10);
}
/**
* 根据ID批量删除
*/
public void testDeleteByIds() {
List ids = new LinkedList();
ids.add(11);
ids.add(12);
peopleMapper.deleteBatchIds( ids );
}
与此同时,也支持基于条件的删除
/**
* 根据条件删除
*/
public void testDeleteByParam1() {
// 表字段map
Map map = new HashMap();
// Note:这里设置条件应使用数据表的字段名,而不是Java类的属性名
map.put("name", "匿名用户");
map.put("sex", "男");
// 多个条件为and的关系
int num = peopleMapper.deleteByMap(map);
System.out.println("delete num : " + num);
}
/**
* 根据条件删除
*/
public void testDeleteByParam2() {
// Note:此时其实隐含了 id为null 的条件
People people = People.builder()
.username("翠花")
.sex("女")
.build();
// 多个条件为and的关系
QueryWrapper<People> wrapper = new QueryWrapper<>(people);
int num = peopleMapper.delete( wrapper );
System.out.println("delete num : " + num);
}
改
同理对于更新操作,支持基于ID的操作方式
/**
* 根据ID更新
*/
public void testUpdateById() {
People people = People.builder()
.id(3)
.username("孙尚香")
.build();
peopleMapper.updateById(people);
}
上述更新语句执行后会发现,id为3的记录,对于name字段确实被更新为 "孙尚香" 了,但是如果sex字段并不会被更新为 NULL。这是因为@TableField注解的updateStrategy属性默认为NOT_NULL所导致的。该属性常用的值及释义如下所示
- NOT_NULL:要求新值非NULL
- NOT_EMPTY:要求新值非NULL、非空字符串
- IGNORED:新值可以为NULL、空字符串
故我们在sex属性上使用@TableField注解,并把updateStrategy设置为FieldStrategy.IGNORED后,上述测试代码对sex字段的更新才会生效
/**
* 性别
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String sex;
与此同时,也支持基于条件的更新。而且可以看到在基于ID的更新方式中,需要修改@TableField注解的updateStrategy属性,来保证可以更新为NULL、空字符串。显然非常麻烦,而且容易出错。而通过updateWrapper的set方法来设置新值,显式地设置NULL值就非常直观了,不容易出错
/**
* 根据条件更新
*/
public void testUpdateByParam() {
UpdateWrapper<People> updateWrapper = new UpdateWrapper<>();
// Note:这里应使用数据表的字段名,而不是Java类的属性名
// where 条件:id 大于 50
updateWrapper.gt("id",50);
// set 新值:sex 更新为 男
updateWrapper.set("sex","男");
// set 新值:name 更新为 NULL
updateWrapper.set("name","null");
// 多个条件为and的关系
peopleMapper.update(null, updateWrapper);
}
查
根据ID查询及批量操作,方式如下
/**
* 根据ID查询
*/
public void testSelectById() {
People people = peopleMapper.selectById(1);
System.out.println("people: " + people);
}
/**
* 根据ID批量查询
*/
public void testSelectByIds() {
List list = new LinkedList();
list.add(1);
list.add(2);
list.add(3);
List<People> peopleList = peopleMapper.selectBatchIds(list);
peopleList.forEach(System.out::println);
}
与此同时,也支持基于条件的查询。其中查询条件为空,则查询全部
/**
* 根据条件查询。其中查询条件为空,则查询全部
*/
public void testSelectAll() {
List<People> list = peopleMapper.selectList(null);
list.forEach( System.out::println );
}
/**
* 根据条件查询
*/
public void testSelectByParam1() {
QueryWrapper<People> queryWrapper = new QueryWrapper<>();
// Note:这里设置条件应使用数据表的字段名,而不是Java类的属性名
// 条件:性别为男
queryWrapper.eq("sex", "男");
// 条件:id 小于等于 100
queryWrapper.le("id", 50);
// 多个条件为and的关系
List<People> list = peopleMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
/**
* 根据条件查询
*/
public void testSelectByParam2() {
// 表字段map
Map<String, Object> map = new HashMap<>();
map.put("sex", "女");
// Note:这里设置条件应使用数据表的字段名,而不是Java类的属性名
map.put("name", "佳丽");
// 多个条件为and的关系
List<People> list = peopleMapper.selectByMap(map);
list.forEach(System.out::println);
}
有时候我们还需要进行分页查询,在Mybatis Plus下也是非常方便的,只需配置下分页插件即可
@Configuration
public class MybatisPlusConfig {
/**
* Mybatis Plus 分页插件
* @return
*/
@Bean
public MybatisPlusInterceptor innerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
关于分页查询的操作方式如下所示:
/**
* 分页查询
*/
public void testSelectByPage() {
// 查询条件
QueryWrapper<People> queryWrapper = new QueryWrapper<>();
// Note:这里设置条件应使用数据表的字段名,而不是Java类的属性名
// 条件:id 大于 2
queryWrapper.gt("id", 2);
// 条件:name字段 (右)模糊匹配 "张%"
queryWrapper.likeRight("name", "张");
// 分页参数: 页码:2, 单页大小:10
Page<People> page = new Page<>(2,10);
// 分页查询, 多个条件为and的关系
Page<People> result = peopleMapper.selectPage(page2, queryWrapper);
System.out.println("people List: " + result.getRecords() );
}
逻辑删除
对于内置Mapper,Mybatis Plus可以自动支持逻辑删除的功能。通过@TableLogic注解指定逻辑删除字段即可
/**
* 逻辑删除标识,invalid:无效;valid:有效
*/
@TableLogic
private String flag;
而对于逻辑未删除的值、已删除的值即可直接通过注解配置,亦可进行全局配置
# Mybatis Plus 全局设置,逻辑已删除值
mybatis-plus.global-config.db-config.logic-delete-value=invalid
# Mybatis Plus 全局设置,逻辑未删除值
mybatis-plus.global-config.db-config.logic-not-delete-value=valid
为了实现逻辑删除,内置Mapper在自动注入SQL时也会发生一些变化。具体地:
- 插入:无变化
- 查找:一方面会追加where条件以过滤掉已删除的记录,另一方面,通过wrapper指定条件也会忽略逻辑删除字段的条件
- 更新:一方面会追加where条件防止对已删除的记录进行更新,另一方面,通过wrapper指定条件也会忽略逻辑删除字段的条件
- 删除:转变为更新语句,将 逻辑删除字段 设置为 逻辑已删除值
Note
对于主键,Mybatis Plus还支持在未指定主键的时候自动生成ID或UUID。具体地,其支持对某个表的单独设置、全局设置。前者可通过在主键属性上设置@TableId注解的type属性为IdType.ASSIGN_ID、IdType.ASSIGN_UUID实现;后者则可通过在配置文件中设置配置项 mybatis-plus.global-config.db-config.id-type 为 assign_id、assign_uuid 实现
Mybatis Plus之内置Mapper实践的更多相关文章
- Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring 非原创[只为记录],原博文地址:https://www.cnblogs.com/ ...
- Mybatis 系列2-配置文件
[Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...
- (转)Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring Mybatis在与Spring集成的时候可以配置MapperFactoryBea ...
- Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 - 推酷 - 360安全浏览器 7.1
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 时间 2014-02-11 21:08:00 博客园-所有随笔区 ...
- 老李分享:持续集成学好jenkins之内置命令
老李分享:持续集成学好jenkins之内置命令 Jenkins命令调用方式:调用Jenkins命令设置job的描述信息. $JAVA_BIN-jar "$JENKINS_CLI_JAR& ...
- zabbix Server 4.0 部署及之内置item使用案例
zabbix Server 4.0 部署及之内置item使用案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.zabbix组件架构概述(图片摘自网络) 1>.zabbi ...
- MyBatis入门程序之Mapper代理方式
Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可,MyBatis会自动为mapper接口生成动态代理实现类. 一.开发规范 1.mapper接口的全限定名要和map ...
- mybatis由浅入深day01_5.3 Mapper动态代理方法
5.3 Mapper动态代理方法(程序员只需要写mapper接口(相当于dao接口)) 5.3.1 实现原理(mapper代理开发规范) 程序员还需要编写mapper.xml映射文件 程序员编写map ...
- mybatis开发Dao的Mapper动态代理方式
1. 开发规范Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体跟Dao原始方法中接口实现类的方法相 ...
随机推荐
- 请说说你对Struts2的拦截器的理解?
Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 拦截器栈(Interceptor Stac ...
- 为什么要配置JDK环境变量?
1. PATH环境变量.作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序.我们需要把 jdk安装目录下的bin目录增加到现有的PATH ...
- STM32 标准库
CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...
- gulp详细基础教程
一.gulp简介 1.gulp是什么? gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器:它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成: ...
- mysql获取表的列名
DESC test4 SHOW COLUMNS FROM test4 SELECT COLUMN_NAME FROM information_schema.columns WHERE table_n ...
- 如何在jsp界面进行判断再输出不同的值
C标签的out <td> <c:if test="${nowtime eq returntime}"> <c:out value="逾期&q ...
- Node自动重启工具 nodemon
为什么要使用 在编写调试Node.js项目,修改代码后,需要频繁的手动close掉,然后再重新启动,非常繁琐.现在,我们可以使用nodemon这个工具,它的作用是监听代码文件的变动,当代码改变之后,自 ...
- 关键字static、extern、volatile、详解及举例
一.预备知识 1. 什么是局部变量?什么是全局变量? 所谓局部变量,就是指在函数内部定义的变量的,只在该函数范围内有效. 全局变量是指,在函数外部定义的变量为外部变量,即全局变量.它 ...
- Python入门-第一行代码到多行代码
不管学啥语言,开始的第一行代码都是: print("hello word") 回车之后,就代表你正式进入代码的世界! 如果报错,恭喜你获得第一个书写bug,请检查单词拼写,双引号, ...
- Linux磁盘分区fdisk命令操作(简洁版)
实例(环境为: CentOS Linux release 7.2.1511 (Core), 3.10.0-327.el7.x86_64) 选择要具体操作的第二块磁盘(linux下一切是文件形式对应): ...