springboot+mybatis+mybaits plus 整合与基本应用

栏目: Java · 发布时间: 5年前

内容简介:在为此,开源上也产生了很多三方对我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

springboot+mybatis+mybaits plus 整合与基本应用

引言

spring framework 所支持的 orm 框架中, mybatis 相比 hibernatespring 本身提供的支持是相对少的,这在开发过程中对使用 mybatis 进行开发的 程序员 来说无疑产生很多难处。

为此,开源上也产生了很多三方对 mybatis 的一些增强工具,比如 ourbatismybatis-generator 等等。这篇我们主要来说下功能丰富、现在还在迭代的一款国人开发的增强工具 mybatis-plus 。就像官方文档说的那样

我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

可以看出, mybatis-plus 是了为了提高效率和简化配置而生的。下面就来展示下在 springboot 下如何整合 mybatis-plus

准备工作

首先是创建一个 springboot 工程

springboot+mybatis+mybaits plus 整合与基本应用

引入相关依赖( springboot 相关、 mybaitsmybatis-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 提供了 BaseMapperBaseService 这些基类来提供一些操作的支持,比如

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 接口

上面说到, BaseMapperBaseService 已经实现了一些基本操作,下面简单说下这些接口的用法

查询

查询中 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语句,并执行。

@Transactional
public 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

更改

提供的 updateupdateOrSaveupateById 都可以实现数据更新。

各自的区别在于

update
updateOrSave
updateById
@Transactional
public 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来装配插件。

@Bean
public 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 囊括了几乎满足日常需要的条件操作,和 jpaspecification 一样,它支持动态产生条件,也支持使用 lambda 表达式去组装条件。他是 QueryWrapperUpdateWrapper 的父类

一些常用的 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 isAsc
LambdaQueryWrapper<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 = val
managerService.update(new Manager(), new UpdateWrapper<Manager>().lambda().set(Manager::getName, "newName").eq(Manager::getManagerId, 4));

诸如还有其他像 eqlteisNullorderByorexists 等限定方法,这里就不一一介绍了。

其他

分页插件

引入分页,除了配置上,还需要添加插件bean

@Bean
public 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 增强工具,提高开发效率。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Effective JavaScript

Effective JavaScript

David Herman / Addison-Wesley Professional / 2012-12-6 / USD 39.99

"It's uncommon to have a programming language wonk who can speak in such comfortable and friendly language as David does. His walk through the syntax and semantics of JavaScript is both charming and h......一起来看看 《Effective JavaScript》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具