springboot+mybatis+mybaits plus 整合与基本应用引言在spring framework所支持的orm框架中,mybatis相比 hibernate,spring本身提供的支持是相对少的,这在开发过程中对使用mybatis进行开发的程序员来说无疑产生很多难处。为此,开源上也产生了很多三方对mybatis的一些增强工具,比如ourbatis、mybatis-generator等等。这篇我们主要来说下功能丰富、现在还在迭代的一款国人开发的增强工具mybatis-plus。就像官方文档说的那样我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。可以看出,mybatis-plus是了为了提高效率和简化配置而生的。下面就来展示下在springboot下如何整合mybatis-plus准备工作首先是创建一个springboot工程引入相关依赖(springboot相关、mybaits、mybatis-plus等等)<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!– springboot对mybaits的自动配置依赖 –> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </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> <!– mybatis-plus相关依赖 –> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> </dependencies>使用mybaits-plus的代码生成器映射生成代码,我们这里所使用的数据库为mysql。这个在另外一篇文章上说明,这里就不讲述了。在这里,mybaits-plus提供了BaseMapper、BaseService这些基类来提供一些操作的支持,比如save(T t)saveOrUpdate(T t)update(T t, Wrapper<T> wrapper)page(IPage<T> page, Wrapper<T> queryWrapper)等等。下面,我们就简单介绍下springboot中怎么运用mybaits-plus配置首先是说到配置,这里默认以yml文件来进行对mybaits-plus的配置。mybatis-plus: #MyBatis Mapper 所对应的 XML 文件位置 mapper-locations: classpath*:mapper/*.xml # MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名, #注册后在 Mapper 对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名(即 XML 中调用的时候不用包含包名) typeAliasesPackage: com.luwei.models # 与 typeAliasesPackage 一起使用,仅扫描以该类作为父类的类 # type-aliases-super-type: java.lang.Object # 配置扫描通用枚举,配置该属性,会对枚举类进行注入 typeEnumsPackage: com.luwei.demo.mybatisplusdemo.envm # 该包下的类注册为自定义类型转换处理类,用于属性类型转换 # type-handlers-package: com.luwei.demo.mybatisplusdemo.handler # 指定 mybatis 处理器 # executorType: simple configuration: #使用驼峰法映射属性,配置这个resultType可以映射 map-underscore-to-camel-case: true global-config: db-config: # 配置表明前缀,例如表设计时表名为tb_manager,对应entity为Manager table-prefix: tb_ #逻辑已删除值 logic-delete-value: 1 #逻辑未删除值 logic-not-delete-value: 0 # 是否开启like查询,即对 stirng 字段是否使用 like,默认不开启 # column-like: false logging: level: # 日志级别,显示操作sql com.luwei.demo.mybatisplusdemo.mapper: debug基本上这些配置都能满足一般的应用了。CRUD 接口上面说到,BaseMapper和BaseService已经实现了一些基本操作,下面简单说下这些接口的用法查询查询中Mybatis-plus提供多种封装好的方式,包括对主键查询、指定条件查询、分页查询等。Manager manager1 = managerService.getById(1);Assert.assertNotNull(manager1);LambdaQueryWrapper<Manager> wrapper = new LambdaQueryWrapper<Manager>().like(Manager::getName, “na”);List<Manager> managerList = managerService.list(wrapper);Assert.assertFalse(managerList.isEmpty());//先配置page分页插件配置Page page = new Page<>(1, 2);IPage<Manager> managerPage = managerService.page(page, wrapper);Assert.assertFalse(managerPage.getRecords().isEmpty());//获取map对象Map<String, Object> map = managerService.getMap(wrapper);System.out.println(map);Object obj = managerService.getObj(wrapper);System.out.println(obj);try { //若有多个结果,抛出异常 managerService.getOne(wrapper, true);}catch (RuntimeException e) { e.printStackTrace(); System.out.println(“异常捕获”);}增加save(T t)方法,实际就是将对象持久化到数据库中,这里会产生一条insert语句,并执行。@Transactionalpublic void add() { Manager manager = new Manager(); manager.setAccount(“account”); manager.setRole(RoleEnum.ROOT); manager.setPassword(“password”); manager.setName(“name”); save(manager);}日志输出:==> Preparing: INSERT INTO tb_manager ( account, name, password, role ) VALUES ( ?, ?, ?, ? ) ==> Parameters: account(String), name(String), password(String), 0(Integer)<== Updates: 1更改提供的update、updateOrSave、upateById都可以实现数据更新。各自的区别在于update:根据条件筛选并更新指定字段updateOrSave:对对象进行更新,对未存储的对象进行插入updateById:根据id对对象进行更新@Transactionalpublic void updateManager() { Manager manager = getById(1); manager.setName(“testUpdate”); updateById(manager); //saveOrUpdate(manager); //update(new Manager(), new UpdateWrapper<Manager>().lambda().set(Manager::getName, “test”).eq(Manager::getManagerId, 1));}删除在删除中,除了一般的物理删除外,mybaits-plus还提供了逻辑删除的支持。如果需要使用逻辑删除,除了上述配置外,还需要添加一个配置bean来装配插件。@Beanpublic ISqlInjector sqlInjector() { return new LogicSqlInjector();}这样在使用删除时,会对记录中标记为删除标识的字段进行更改,在查询和更新时,也只是针对删除标识为未删除的记录。public void deleteManager() { LambdaQueryWrapper<Manager> wrapper = new LambdaQueryWrapper<Manager>().eq(Manager::getManagerId, 4); System.out.println(baseMapper.delete(wrapper)); /Map<String, Object> deleteMap = new HashMap<>(); //使用表字段名 deleteMap.put(“manager_id”, 4); baseMapper.deleteByMap(deleteMap);/ /baseMapper.deleteById(4);/ //属于service下的方法 /LambdaQueryWrapper<Manager> wrapper = new LambdaQueryWrapper<Manager>().eq(Manager::getManagerId, 4); remove(wrapper);/}条件构造器在查询、更新、删除这些操作中,我们往往需要定义条件或者设置属性,也就是where子句和set语句,如果不是直接通过sql去处理,在mybatis-plus中,也提供了一种包装器来实现。AbstractWrapper囊括了几乎满足日常需要的条件操作,和jpa的specification一样,它支持动态产生条件,也支持使用lambda表达式去组装条件。他是QueryWrapper和UpdateWrapper的父类一些常用的wrapper方法Map<String, Object> conditionMap = new HashMap<>();//使用表字段名conditionMap.put(“name”, “name”);conditionMap.put(“manager_id”, 1);//allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)//filter:忽略字段//null2IsNull:为true则在map的value为null时调用 isNull 方法,为false时则忽略value为null的QueryWrapper<Manager> queryWrapper = new QueryWrapper<Manager>().allEq((r, v) -> r.indexOf(“name”) > 0, conditionMap, true);managerService.list(queryWrapper);//like(R column, Object val) -> column like ‘%na%’//likeLeft -> column like ‘%na’//likeRight -> column like ’na%’//and(Function<This, This> func) -> and (column = val)LambdaQueryWrapper<Manager> lambdaWrapper = new LambdaQueryWrapper<Manager>().like(Manager::getName, “na”).and((r) -> r.eq(Manager::getDisabled, false));managerService.list(lambdaWrapper);//orderBy(boolean condition, boolean isAsc, R… columns) -> order by columns isAscLambdaQueryWrapper<Manager> lambdaWrapper = new LambdaQueryWrapper<Manager>().orderBy(true, false, Manager::getManagerId);managerService.list(lambdaWrapper);//select 用于挑选属性LambdaQueryWrapper<Manager> lambdaWrapper = new LambdaQueryWrapper<Manager>().select(Manager::getName, Manager::getDisabled);managerService.list(lambdaWrapper);//set(R column, Object val) -> update T set colunm = valmanagerService.update(new Manager(), new UpdateWrapper<Manager>().lambda().set(Manager::getName, “newName”).eq(Manager::getManagerId, 4));诸如还有其他像eq,lte,isNull,orderBy,or,exists等限定方法,这里就不一一介绍了。其他分页插件引入分页,除了配置上,还需要添加插件bean@Beanpublic PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor();}在使用时,自定义查询中,参数中添加Page对象,并要求放在参数中的第一位IPage<ManagerPageVO> selectManagerPage(Page page, @Param(“roleEnum”)RoleEnum roleEnum, @Param(“managerId”) Integer managerId, @Param(“name”) String name);<select id=“selectManagerPage” resultType=“com.luwei.pojos.manager.ManagerPageVO”> <![CDATA[ select manager_id, account, name, role, disabled, create_time, last_login_time from tb_manager where role = #{roleEnum} and deleted = false ]]> <if test=“name != null”> <![CDATA[ and (name like CONCAT(’%’,#{name},’%’) or account like CONCAT(’%’,#{name},’%’)) ]]> </if> <if test=“managerId != null”> <![CDATA[ and manager_id = #{managerId} ]]> </if></select><select id=“selectForSpecialCondition” resultType=“com.luwei.entity.Manager”> select <include refid=“Base_Column_List” /> from tb_manager where name like ‘%admin%’</select>主键配置在mybaits-plus中,有多种主键生成策略,它们分别是IdType.AUTO:数据库id自增IdType.INPUT:用户输入IdType.ID_WORKER:唯一ID,自动填充(默认)IdType.UUID:唯一ID,自动填充由于我们公司使用的是mysql本身的自增策略,所以选择使用 IdType.AUTO。@ApiModelProperty(value = “管理员id”)@TableId(value = “manager_id”, type = IdType.AUTO)private Integer managerId;至于 ID_WORKER 和 UUID 的不同,在于它们的唯一键生成策略不同,ID_WORKER 按照官方的介绍,是使用Sequence作为基础产生唯一键。枚举属性为了让mybaits更好地使用枚举,mybatis-plus提供了枚举扫描注入具体配置,首先是配置扫描路径# 配置扫描通用枚举,配置该属性,会对枚举类进行注入typeEnumsPackage: com.luwei.demo.mybatisplusdemo.envm在枚举类中实现接口,用于获取具体值//实现此接口用于获取值public interface BaseEnum<E extends Enum<?>, T> { T getValue(); String getDisplayName();}这样,基本上就可以在mybatis上使用枚举类型了。总结上面描述了mybitis-plus基本用法,其实除了以上,它还提供了很多方便的插件和应用,包括xml热加载、乐观锁插件、性能分析插件等,这些由于篇幅和主题的原因我就不在这里阐述了。希望这篇可以带你很快地上手这个当前热门的mybaits增强工具,提高开发效率。