前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >认识MyBatis的好兄弟 MyBatis - Plus

认识MyBatis的好兄弟 MyBatis - Plus

作者头像
cxuan
发布2019-09-17 17:08:10
8350
发布2019-09-17 17:08:10
举报
文章被收录于专栏:Java建设者

快速搭建

我们先通过一个简单的Demo 来认识一下 MyBatis - Plus 的搭建和用法:

现在数据库中创建一张 User 表,表结构和数据如下

id

name

age

email

1

lx

21

15831197211@163.com

2

cxuan

20

15831197212@163.com

3

liux

28

15831197213@163.com

4

xiaona

21

15831197214@163.com

5

lxuan

24

15831197215@163.com

对应的建表语句和SQL语句如下

代码语言:javascript
复制
DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);

INSERT INTO `user` VALUES (1, 'lx', 21, '15831197211@163.com');
INSERT INTO `user` VALUES (2, 'cxuan', 20, '15831197212@163.com');
INSERT INTO `user` VALUES (3, 'liux', 28, '15831197213@163.com');
INSERT INTO `user` VALUES (4, 'xiaona', 21, '15831197214@163.com');
INSERT INTO `user` VALUES (5, 'lxuan', 24, '15831197215@163.com');

使用 IDEA 新建一个 SpringBoot 项目,构建完成后,在 pom.xml添加如下依赖:

代码语言:javascript
复制
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.2.0</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
  </dependency>
</dependencies>

新建 application.yml ,在yml 文件上添加如下数据库驱动信息

代码语言:javascript
复制
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis
    username: root
    password: 123456

在主方法上添加 @MapperScan 注解,扫描mapper 包下面的内容

代码语言:javascript
复制
@SpringBootApplication
@MapperScan("com.mybatis.plus.mapper")
public class MybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }

}

新建一个 User 类,使用 @Data lombok 中的注解,如下

代码语言:javascript
复制
@Data
public class User {

    private long id;
    private String name;
    private Integer age;
    private String email;
}

然后新建一个接口,这个接口实现 BaseMapper接口

代码语言:javascript
复制
public interface UserMapper extends BaseMapper<User> {}

使用单元测试进行测试:

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void contextLoads() {
        System.out.println("----- selectAll method test -----");
        List<User> userList = userMapper.selectList(null);
        Assert.assertEquals(5,userList.size());
        userList.forEach(System.out::println);
    }

}

输出:

User(id=1, name=lx, age=21, email=15831197211@163.com) User(id=2, name=cxuan, age=20, email=15831197212@163.com) User(id=3, name=liux, age=28, email=15831197213@163.com) User(id=4, name=xiaona, age=21, email=15831197214@163.com) User(id=5, name=lxuan, age=24, email=15831197215@163.com)

通过以上几个简单的步骤,我们就实现了 User 表的 查询 功能,你没有看到一条 SQL 语句和 映射的编写。

从以上步骤中,我们可以看到集成MyBatis-Plus非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。

特性

  • 无侵入: 只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小: 启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作: 内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用: 通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成: 支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式: 支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作: 支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器: 采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件: 基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库: 支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多种数据库
  • 内置性能分析插件: 可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件: 提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

MyBatis 核心功能

Mapper CRUD 接口

“说明:

  • 通用 CRUD 封装BaseMapper[1]接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器
  • 泛型 T 为任意实体对象
  • 参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定,每一张表都有自己的唯一 id 主键
  • 对象 Wrapper条件构造器[2]

看下其基本使用

Insert

insert 只有一种用法,直接插入对象的实体

代码语言:javascript
复制
/**
 * 插入一条记录
 * @param entity 实体对象
 * @return 插入成功记录数
 */
int insert(T entity);
验证

我们先为 User 实体类添加 @AllArgsConstructor 注解,如果 Lombok 不熟的同学请移步至 这些极简的注解你都清楚吗 这篇文章一探究竟。

下面是测试所用的代码

代码语言:javascript
复制
@Test
public void insertUserEntity(){
  userMapper.insert(new User(6,"cxuanxuan",25,"15831197216@163.com"));
}

“注意 Junit 中测试的 insert 插入方法是没有返回值的,不然会报错,所以返回类型是void 。但其实 insert 方法是有返回值的,返回的是插入成功的记录数。

Delete

delete 有四种用法,分别是根据 id 删除、通过某个表字段删除、通过实体类删除和批量删除,比我们最初只是通过 id 删除功能强大很多。

代码语言:javascript
复制
/**
 * 根据 ID 删除
 * @param id 主键ID
 * @return 删除成功记录数
 */
int deleteById(Serializable id);

/**
 * 根据 columnMap 条件,删除记录
 * @param columnMap 表字段 map 对象
 * @return 删除成功记录数
 */
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

/**
 * 根据 entity 条件,删除记录
 * @param wrapper 实体对象封装操作类(可以为 null)
 * @return 删除成功记录数
 */
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

/**
 * 删除(根据ID 批量删除)
 * @param idList 主键ID列表(不能为 null 以及 empty)
 * @return 删除成功记录数
 */
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
验证

验证示例如下:

代码语言:javascript
复制
// 根据某个特定的 id 进行删除。
@Test
public void deleteUserById(){
  userMapper.deleteById(6);
}

// deleteByMap 参数是 Map<String, Object> 类型
// 第一个范型是字段名称,第二个范型是字段对应的值
@Test
public void deleteByColumnMap(){
  Map<String,Object> columnMap = new HashMap<>();
  columnMap.put("id",4);
  userMapper.deleteByMap(columnMap);
}

// 使用 QueryWrapper 进行条件筛选
@Test
public void deleteEntity(){
  QueryWrapper<User> queryWrapper = new QueryWrapper();
  // 删除 name 不为 null ,并且 age 大于等于 28的记录
  queryWrapper.isNotNull("name").ge("age",28);
  userMapper.delete(queryWrapper);
}

// 根据 Collection 集合进行删除,也可以是 Collection 的子类
@Test
public void deleteBatch(){
  List list = new ArrayList();
  // 批量删除 1 和 2 的数据
  list.add(1);
  list.add(2);
  userMapper.deleteBatchIds(list);
}

上面是 Delete 方法的测试例子,其中 **deleteByColumnMap 和 deleteEntity ** 方法如果不传任何值,默认删除表中所有的数据。deleteBatch 如果传递 null 的话,测试会报错,无法通过单元测试。

Update

Update 更新方法只有两种形式,一种是直接根据 id 修改实体属性的值,一种是直接更新实体类

代码语言:javascript
复制
/**
 * 根据 ID 修改
 * @param entity 实体对象
 * @return 修改成功记录数
 */
int updateById(@Param(Constants.ENTITY) T entity);

/**
 * 根据 whereEntity 条件,更新记录
 * @param entity        实体对象 (set 条件值,可为 null)
 * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
 * @return 修改成功记录数
 */
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
验证
代码语言:javascript
复制
// 根据id更新User表
@Test
public void updateUserById(){
  userMapper.updateById(new User(5,"cxuaner",25,"15831197216@163.com"));
}

// 更新 User 实体类信息
@Test
public void updateUserEntity(){
  UpdateWrapper<User> updateWrapper = new UpdateWrapper();
  updateWrapper.eq("age",28);
  userMapper.update(new User(3,"cxuan",22,"15831197213@163.com"),updateWrapper);
}
  • 第一条 updateUserById 语句是根据 id 进行更新,传入一个实体类的意思是更新 id = 5的这条记录。 传入 null 会报错,如果没有 id = 5的这条记录,测试会成功,但是不会更新任何记录
  • 第二条 updateUserEntity 语句是根据实体类的条件进行更新,UpdateWrapper 是一个条件构造器,测试的是 age 为 28 的这条记录进行更新。 条件构造器后面会进行更加详细的介绍。

Select

Select 用法比较多,现在来一起看一下Select 有哪些用法

代码语言:javascript
复制
/**
 * 根据 ID 查询
 * @param id 主键ID
 * @return 实体
 */
T selectById(Serializable id);

/**
 * 查询(根据ID 批量查询)
 * @param idList 主键ID列表(不能为 null 以及 empty)
 * @return 实体集合
 */
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

/**
 * 查询(根据 columnMap 条件)
 * @param columnMap 表字段 map 对象
 * @return 实体集合
 */
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

/**
 * 根据 entity 条件,查询一条记录
 * @param queryWrapper 实体对象
 * @return 实体
 */
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根据 Wrapper 条件,查询总记录数
 * @param queryWrapper 实体对象
 * @return 满足条件记录数
 */
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根据 entity 条件,查询全部记录
 * @param queryWrapper 实体对象封装操作类(可以为 null)
 * @return 实体集合
 */
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根据 Wrapper 条件,查询全部记录
 * @param queryWrapper 实体对象封装操作类(可以为 null)
 * @return 字段映射对象 Map 集合
 */
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根据 Wrapper 条件,查询全部记录
 * 注意:只返回第一个字段的值
 * @param queryWrapper 实体对象封装操作类(可以为 null)
 * @return 字段映射对象集合
 */
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根据 entity 条件,查询全部记录(并翻页)
 * @param page         分页查询条件(可以为 RowBounds.DEFAULT)
 * @param queryWrapper 实体对象封装操作类(可以为 null)
 * @return 实体分页对象
 */
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根据 Wrapper 条件,查询全部记录(并翻页)
 * @param page         分页查询条件
 * @param queryWrapper 实体对象封装操作类
 * @return 字段映射对象 Map 分页对象
 */
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
验证

下面就对上面的示例方法进行验证

代码语言:javascript
复制
/**
* 查询id = 1 的一条记录
*/
@Test
public void selectById(){
  User user = userMapper.selectById(1);
  System.out.println("user = " + user);
}

/**
* 批量查询id = 1,2,3 的记录
*/
@Test
public void selectUserBatchId(){
  List batchIds = new ArrayList();
  batchIds.add(1);
  batchIds.add(2);
  batchIds.add(3);
  List list = userMapper.selectBatchIds(batchIds);
  System.out.println("list = " + list);
}

/*
* 查询年龄为 21 岁的记录,并循环遍历输出
*/
@Test
public void selectUserByMap(){
  Map<String,Object> userMap = new HashMap<>();
  userMap.put("age",21);
  List<User> users = userMapper.selectByMap(userMap);
  users.forEach(p-> {
    System.out.println(p);
  });
}

/**
* 根据 entity 条件,查询一条id = 1 的记录,需要手动添加 User(long id)的构造器
*/
@Test
public void selectOneUser(){
  
  // 需要在 User 类上添加一个 id 的构造函数
  User user = userMapper.selectOne(new QueryWrapper<>(new User(1)));
  System.out.println("user = " + user);
}

/**
* 根据 Wrapper 条件,查询年龄大于 22 的总条目数
*/
@Test
public void selectCountNum(){
  QueryWrapper<User> queryWrapper = new QueryWrapper();
  queryWrapper.ge("age",22);
  Integer integer = userMapper.selectCount(queryWrapper);
  System.out.println("查询出来的总记录数 = " + integer);
}

/*
* 查询年龄大于22 的所有记录数,返回一个List
*/
@Test
public void selectUserList(){
  QueryWrapper<User> queryWrapper = new QueryWrapper();
  queryWrapper.ge("age",22);
  List<User> users = userMapper.selectList(queryWrapper);
  users.forEach(p-> {
    System.out.println(p);
  });
}

/*
* 查询年龄大于22 的所有记录数,返回的是一个List<Map>
*/
@Test
public void selectUserMaps(){
  QueryWrapper<User> queryWrapper = new QueryWrapper();
  queryWrapper.ge("age",22);
  List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
  maps.forEach(p-> {
    System.out.println(p);
  });
}

/**
* 查询年龄大于22 的所有记录数,返回的是一个List<Object>
* 注意:只返回第一个字段的值
*/
@Test
public void selectUserObject(){
  QueryWrapper<User> queryWrapper = new QueryWrapper();
  queryWrapper.ge("age",22);
  List<Object> objects = userMapper.selectObjs(queryWrapper);
  objects.forEach(p-> {
    System.out.println(p);
  });
}

参考资料

[1]

BaseMapper: https://gitee.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/mapper/BaseMapper.java

[2]

条件构造器: https://mp.baomidou.com/guide/wrapper.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java建设者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 快速搭建
  • 特性
  • MyBatis 核心功能
    • Mapper CRUD 接口
      • Insert
        • 验证
      • Delete
        • 验证
      • Update
        • 验证
      • Select
        • 验证
      • 参考资料
      相关产品与服务
      数据库
      云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档