MyBatisPlus简介
MP官方介绍:https://mp.baomidou.com/
MP是MyBatis的增强版,在MyBatis基础之上扩充了其他功能,旨在简化开发、提高效率。
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
MyBatisPlus实战
SpringBoot项目整合MP
-
在IDEA中下载mybatisx插件。
-
在pom.xml中引入MP的依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>Latest Version</version> </dependency>
-
dao层接口继承 Baseapper 类
BaseMapper是MP封装好的类,里面定义了常用的CRUD方法。
-
在启动类添加 @MapperScan("mapper") 注解,扫描Mapper类
通过以上简单的配置,可以使用MP实现简单的CRUD操作,省去了Mapper.xml映射文件
实现CRUD操作
在控制台打印Sql语句
-
单数据源
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
-
多数据源
public class MybatisPlusConfig{ @Bean("sqlSessionFactory") public SqlSessionFactory sqlSessionFactory() throws Exception { // 导入mybatissqlsession配置 MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean(); // 指明数据源 sessionFactory.setDataSource(multipleDataSource(dataSource0(), dataSource1(), dataSource2())); // 指明mapper.xml位置(配置文件中指明的xml位置会失效用此方式代替,具体原因未知) sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/**Mapper.xml")); // 指明实体扫描(多个package用逗号或者分号分隔) sessionFactory.setTypeAliasesPackage("gsa.geographic.system.entity"); // 导入mybatis配置 MybatisConfiguration configuration = new MybatisConfiguration(); configuration.setJdbcTypeForNull(JdbcType.NULL); configuration.setMapUnderscoreToCamelCase(true); configuration.setCacheEnabled(false); // 配置打印sql语句 configuration.setLogImpl(StdOutImpl.class); sessionFactory.setConfiguration(configuration); // 添加分页功能 sessionFactory.setPlugins(new Interceptor[]{ paginationInterceptor() }); // 导入全局配置 sessionFactory.setGlobalConfig(globalConfiguration()); return sessionFactory.getObject(); } }
CRUD操作
在Spring Boot项目中配置好MP后,就可以进行简单的CRUD操作了。
BaseMapper类
提供了通用的CRUD方法,如下:
int insert(T entity);//插入一条记录
int deleteById(Serializable id);//根据ID删除
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);//根据columnMap条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);//根据entity条件,删除记录
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);//删除(根据ID批量删除)
int updateById(@Param(Constants.ENTITY) T entity);//根据ID修改
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);//根据whereEntity条件,更新记录
T selectById(Serializable id);//根据ID查询
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);//查询(根据ID批量查询)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);//查询(根据columnMap条件)
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);//根据entity条件,查询一条记录
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);//根据 Wrapper条件,查询总记录数
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);//根据 entity 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);//根据Wrapper条件,查询全部记录
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);//根据Wrapper条件,查询全部记录
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);//根据entity条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);//根据Wrapper 条件,查询全部记录(并翻页)
如何使用?让项目中的Mapper接口继承BaseMapper即可。
public interface UserMapper extends BaseMapper<User> {
}
常用注解
@TableName
一般情况下,实体名和数据库表名是根据驼峰命名规则相对应的,如SysUser类对应sys_user表。如果我们需要修改表名或类名,此时根据规则对应失效,MP提供了@TableName注解,我们直接可以修改实体类和数据库表的对应关系。
@TableName(value = "t_user")
public class User
@TableId
插入数据时,如果我们不指定主键Id的值,MP会为我们自动填充主键Id,仅在实体类中主键名为id下才有效。如果我们想定义的主键为userId,@TableId可以指定实体类中的主键。
@TableId
private Long userId;
//还可以对应列名
@Table(value = "id")
private Long userId;
@TableField
用在非主键字段,和@TableName相同,用在非主键字段上可以对应数据库字段名的值。
@TableField(value = "user_name")
private String name;
排除非表字段
实体类属性不存在于数据库表中,由于MP为属性和字段做了一一映射,所以如果存在非表字段的属性时会报错。
排除非表字段的三种方法
transient关键字
private transient String weChat;
定义为静态变量
private static String weChat;
//如果使用了lombok,它不会为静态变量创建getter和setter方法,所以我们需要手动创建。
@TableField的 exist 属性
@TableField(exist = false)
private String weChat;
插入
简单插入一条数据:
@Test
public void addTest() {
User user = new User();
user.setId(3L);
user.setName("ez");
user.setAge(20);
user.setEmail("ezez@qq.com");
user.setManagerId(1L);
user.setCreateTime(LocalDateTime.now());
userMapper.insert(user);
}
查询
通过Id查询:
@Test
public void selectById() {
User user = userMapper.selectById(3L);
System.out.println(user); //打印成功
}
通过Id集合查询:
@Test
public void selectBatchIds() {
//selectBatchIds方法传递的集合不能为null或empty
List<User> userList = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
userList.forEach(System.out::println);
}
通过Map查询:
@Test
public void selectByMap() {
Map<String, Object> map = new HashMap<>();
map.put("user_name", "mike");
// key代表的是数据库中的字段名,而不是实体属性名
List<User> userList = userMapper.selectByMap(map);
// 生成SQL:SELECT id,user_name AS name,age,email,manager_id,create_time,update_time,version,delete_id
// FROM t_user WHERE user_name = ?
userList.forEach(System.out::println);
}
更新
根据Id更新:
@Test
public void addTest() {
User user = new User();
user.setId(2L);
user.setName("tom");
user.setAge(15);
user.setEmail("tomtom@qq.com");
user.setManagerId(null);
user.setCreateTime(LocalDateTime.now());
userMapper.updateById(user);// 调用该方法,更新成功!
}
使用UpdateWrapper的set方法:
@Test
public void updateByWrapper() {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("user_name", "tom").set("age", 7);
int rows = userMapper.update(null, updateWrapper);
System.out.println(rows);
}
LambdaUpdateWrapper:
@Test
public void UpdateByLambdaWrapper() {
LambdaUpdateWrapper<User> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
lambdaUpdateWrapper.eq(User::getName, "tom").set(User::getAge, 24);
int rows = userMapper.update(null, lambdaUpdateWrapper);
System.out.println(rows);
}