## 第四章 Spring Boot框架集成Mybatis-plus 国产的开源框架,基于mybatis,相当于对mybatis进行了二次的封装,是2019年开源中国里面排行第一的框架,它的核心功能就是简化mybatis开发,提高效率。 官网:https://mp.baomidou.com/ [MyBatis-Plus (opens new window)](https://github.com/baomidou/mybatis-plus)(简称 MP)是一个 [MyBatis (opens new window)](http://www.mybatis.org/mybatis-3/)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 使用第三方组件: - 导入对应的依赖 - 写相应的配置 - 编写代码 找依赖的官网:https://mvnrepository.com/ #### 一、快速上手步骤 1、创建数据库、数据表 2、创建SpringBoot项目 3、导入依赖 ~~~xml <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- Druid依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency> ~~~ 如果是springboot3,则替换一下依赖 ~~~xml <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.6</version> </dependency> ~~~ 注意:导入mybatis-plus的依赖就不需要导入mybatis依赖了,它自己已经做了集成,目前还没有接入spring的官方孵化器。 4.编写配置 ~~~yaml spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/shop_db?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false username: root password: root druid: initial-size: 20 min-idle: 20 max-active: 100 max-wait: 10000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 30000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: true test-on-return: false ~~~ 5、创建对应的entity、mapper 使用通用mapper ~~~java @Repository public interface UserMapper extends BaseMapper<User> { } ~~~ 在对应的mapper上面继承基本的接口 BaseMapper,至此所有的CRUD操作已经编写完成了。 6、在主启动类上添加配置 ```java @MapperScan("cn.hxzy.mapper") ``` 7、编写测试代码 继承了BaseMapper,所有的方法全部来自父类,当然我们也可以扩展编写自己的方法。 提一下这个Wrapper,它是条件构造器,可以在里面添加很多查询条件。 #### 二、配置yml 现在所有的sql是不可见的,我们希望看到sql的执行过程,所以配置日志,配置映射xml位置,配置别名 ~~~yaml # mybatis-plus配置 mybatis-plus: configuration: map-underscore-to-camel-case: false log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志配置 type-aliases-package: cn.hxzy.entity mapper-locations: classpath:/mapper/*Mapper.xml ~~~ 配置xml ~~~xml <?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.hxzy.mybatisplus.mapper.UserMapper"> </mapper> ~~~ #### 三、CRUD操作 mapper接口的常用方法: ~~~java @Autowired private UserMapper userMapper; @Test void getUser1() { //查询单个对象 User user = userMapper.selectById(2L); System.out.println(user); } @Test void getUser2(){ //查询单个对象 QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("id",1L); User user = userMapper.selectOne(queryWrapper); System.out.println(user); } @Test void getList(){ //条件构造器 where id=1 queryWrapper.eq("id",1); //QueryWrapper<User> queryWrapper=new QueryWrapper<>(); //查询集合数据 List<User> userList = userMapper.selectList(null); for (User user : userList) { System.out.println(user); } } @Test void insert(){ //新增操作 int num = userMapper.insert(new User(6L, "张三", 22, "87747@qq.com")); if(num>0){ System.out.println("新增数据成功"); } } @Test void update1(){ //1、修改第1种 User user = new User(6L, "张三丰", 122, "87747@qq.com"); int num = userMapper.updateById(user); if(num>0){ System.out.println("修改数据成功"); } } @Test void update2(){ //2、修改第2种 User user = new User(6L, "张三丰", 122, "87747@qq.com"); UpdateWrapper<User> updateWrapper=new UpdateWrapper<>(); updateWrapper.eq("id",6L); //条件where语句 updateWrapper.set("name","张无忌"); //set设值 int num = userMapper.update(updateWrapper); if(num>0){ System.out.println("修改数据成功"); } } @Test void update3(){ //3、修改第3种 User user = new User(6L, "李四", 32, "87747@qq.com"); UpdateWrapper<User> updateWrapper=new UpdateWrapper<>(); updateWrapper.eq("id",6L); //条件where语句 int num = userMapper.update(user,updateWrapper); if(num>0){ System.out.println("修改数据成功"); } } @Test void delete1(){ //删除1 int num = userMapper.deleteById(6L); if(num>0){ System.out.println("删除成功"); } } @Test void delete2(){ //删除2 QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("id",5L); int num = userMapper.delete(queryWrapper); if(num>0){ System.out.println("删除成功"); } } @Test void delete3(){ //删除3 User user = new User(); user.setId(6L); int num = userMapper.deleteById(user); if(num>0){ System.out.println("删除成功"); } } ~~~ #### 四、常用注解 @TableName 用来映射数据库的表名,如果表名与实体类名不一致,在实体类上添加 ~~~java @TableName(value="表名") ~~~ @TableField 用来映射字段,用法同上 ~~~java //表明:此字段不属于表的列 @TableField(exist=false) @TableField(value="列的字段名") ~~~ @TableId 设置注解映射 ~~~java @TableId(type = IdType.ASSIGN_ID) private Long userId; ~~~ 查看这个枚举类型IdType: ~~~java AUTO(0), NONE(1), INPUT(2), ASSIGN_ID(3), ASSIGN_UUID(4); private final int key; private IdType(int key) { this.key = key; } public int getKey() { return this.key; } ~~~ 主键生成策略: | 值 | 描述 | | ----------- | ------------------------------------------------------------ | | AUTO | 数据库自增 | | NONE | MP 自己设置注解,采用雪花算法实现 实体类使用String,数据库使用bigint | | INPUT | 需要开发者手动赋值 【】住院号:062415 000001 000002 062415 99999999 | | ASSIGN_ID | MP 分配ID, 可以使用Long,Integer, String 花算法实现 | | ASSIGN_UUID | 分配UUID,主键类型必须是String | 分布式系统唯一ID生成策略之雪花算法 SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的。 在@TableField主键 的属性里设置 exit=false ,表示不是数据库字段,就不会映射了,一般用于DTO,VO等 select=false 表示就不去查询 #### 五、使用fill完成字段自动填充 @TableField 的属性,表示自动填充,将对象存入数据库的时候,由mybatis-plus自动给某些字段赋值,create_time,update_time等 步骤: 1、数据库必须先添加字段,然后实体类加注解 ~~~java @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; ~~~ 2、创建自动填充的处理器 ~~~java @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { //metaObject 元数据 this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime",new Date(),metaObject); } } ~~~ 3、测试 略 **注意**: 1、实体的属性如果为整数类型,就使用Integer类型,因为在使用自动填充的时候,int类型会有一个默认值0。 2、在使用自动填充的时候,修改语句不能使用条件构造器为参数的方法,因为此方法限定了要改动的列,所以会让自动填充失效。 ~~~java userMapper.update(updateWrapper); //此方法会让自动填充失效 ~~~ #### 六、逻辑删除 1、在数据库上扩展列deleted 2、实体类上扩展属性 ~~~java private Integer deleted; ~~~ 3、配置文件上添加 ~~~yml mybatis-plus: global-config: db-config: logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) ~~~ #### 七、乐观锁插件 乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。 乐观锁:是一种基于冲突检测的方法,检测到冲突时操作就会失败。在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。 悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。 解决事务之间的丢失更新 实现步骤: 1、数据库上扩展version的字段 ,设置默认值为1 2、实体类上添加version属性 ,添加@Version注解 3、配置乐观锁插件 ~~~java package cn.hxzy.config; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisplusConfig { /** * 新版 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mp = new MybatisPlusInterceptor(); mp.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return mp; } } ~~~ 4、测试乐观锁是否生效 ~~~java @Test public void test(){ User user = userMapper.selectById(5L); user.setAge(169); //模拟一个捷足先登的第三方 user.setVersion(user.getVersion()+1); userMapper.updateById(user); } ~~~ #### 八、条件构造器 条件构造器方法: ~~~java QueryWrapper<T> wrapper=new QueryWrapper<T>(); ~~~ 1.eq:等于 ~~~java wrapper.eq("id","1415862105323061249"); ~~~ 2.gt:大于 ge: 大于等于 ~~~java wrapper.gt("age",24); ~~~ 3.lt 小于 le:小于等于 4.ne:不等于 5.like: 模糊查询 likeLeft: 百分号在左边 likeRight: 百分号在右边 ~~~java wrapper.like("name","郭"); ~~~ 6.排序 ~~~ java wrapper.orderByDesc("age"); ~~~ 7.map封装条件 ~~~java Map<String,Object> maps=new HashMap<String,Object>(); maps.put("age",24); maps.put("name","Billie"); === wrapper.allEq(maps); ~~~ 8.in ~~~java wrapper.in("id",list); ~~~ 9.inSql ~~~java QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.inSql("id", "10"); wrapper.inSql(true, "id", "4"); User user = userMapper.selectOne(wrapper); List<User> list = userMapper.selectList(wrapper); list.forEach(System.out::print); ~~~ 10. updateWrapper ~~~java UpdateWrapper<User> updateWrapper=new UpdateWrapper<>(); ~~~ #### 九、分页查询操作 1.配置 mybatisplus内置了分页插件,配置拦截器组件 ~~~java package cn.hxzy.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisplusConfig { /** * 新版:乐观锁与分页插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } } ~~~ 2.测试 ~~~java @Test public void testPage(){ QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.like("name","张"); //Page的构造方法,参数1代表页码,参数2代表每页显示多少条记录 Page<User> page=new Page<>(2,3); userMapper.selectPage(page,wrapper); List<User> records = page.getRecords(); //得到记录集合 long total = page.getTotal(); //获取总记录数 System.out.println("总记录数:"+total); records.forEach(System.out::println); } ~~~ #### 十、代码生成器 让代码来写代码,让代码来生成一个项目结构。 -逆向工程 AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、ServiceImpl、Controller 等各个模块的代码,极大的提升了开发效率。 1.导入MybatisPlus Generator依赖 ~~~xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.3.1.tmp</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <!--swagger2 核心依赖--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- swagger-ui为项目提供api展示及测试的界面--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> ~~~ 2.生成器 ~~~java package cn.hxzy; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; public class MybatisPlus_Generator { public static void main(String[] args) { //创建generator对象 AutoGenerator autoGenerator = new AutoGenerator(); //1、配置数据源 DataSourceConfig DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/ticket?serverTimezone=GMT%2B8&useUnicode=true&useSSL=false&characterEncoding=utf8"); dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver"); dataSourceConfig.setUsername("root"); dataSourceConfig.setPassword("root"); autoGenerator.setDataSource(dataSourceConfig); //2、全局配置 GlobalConfig GlobalConfig globalConfig = new GlobalConfig(); //项目生成的路径 globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java"); globalConfig.setAuthor("shujun.Meng"); //作者 globalConfig.setOpen(false); //项目创建完毕后,是否要打开资源目录 globalConfig.setFileOverride(false);//是否覆盖原来生成的代码 //UserService globalConfig.setServiceName("%sService");//生成的service里面没有I的前缀 globalConfig.setSwagger2(true);//开启Swagger的配置 globalConfig.setDateType(DateType.ONLY_DATE);//关于日期的设置 autoGenerator.setGlobalConfig(globalConfig); //3、包信息 PackageConfig packageConfig = new PackageConfig(); packageConfig.setParent("cn.hxzy.teacher"); //packageConfig.setModuleName("user");//设置模块名称 一会 packageConfig.setController("controller"); packageConfig.setService("service"); packageConfig.setServiceImpl("service.impl"); packageConfig.setMapper("mapper"); packageConfig.setEntity("entity"); //packageConfig.setXml("mapper.xml"); autoGenerator.setPackageInfo(packageConfig); //4、配置策略 StrategyConfig strategyConfig = new StrategyConfig(); //去掉数据表的前缀 strategyConfig.setTablePrefix("sys_"); //去掉数据表字段的前缀 strategyConfig.setFieldPrefix("user_"); strategyConfig.setEntityLombokModel(true);//添加Lombok注解 strategyConfig.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略 strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);//下划线转驼峰 strategyConfig.setInclude("sys_user"); //要生成的数据表 autoGenerator.setStrategy(strategyConfig); //5、执行 autoGenerator.execute(); } } ~~~ #### 十一、通用Service 通用servcie接口 ~~~java public interface UserService extends IService<User> { } ~~~ 实现类 ~~~java @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { } ~~~ 查询 ~~~ list(); list(queryWrapper); getById(id); ~~~ 删除 ~~~ removeById(id); remove(条件构造器); ~~~ 新增 ~~~ save(实体类); saveOrUpdate(实体类);//实体类上如果有ID值,则是修改操作,如果ID为空,则是新增操作 saveBatch(集合);//批量新增 ~~~ 修改 ~~~ updateById(实体类);//根据实体类的ID值进行修改 update(条件构造器); ~~~
Spring Boot框架集成Mybatis-plus
最新推荐文章于 2024-08-30 18:34:55 发布