衡云blog系列--2.集成篇,springboot集成mybatis-plus及generate

一 基础

简介

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具, 是国内人员开发的 MyBatis 增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

特性

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

框架结构

衡云blog系列--2.集成篇,springboot集成mybatis-plus及generate_第1张图片

二 项目搭建

对应的数据库脚本

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)
);

数据库data脚本

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

数据库准备完成后我们来通过springboot创建初始化一个工程。初始化工程的步骤我就不阐述了,有不知道的小伙伴自行baidu

pom.xml展示

    
    
    
        org.springframework.boot
        spring-boot-starter-freemarker
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
    
        org.springframework.boot
        spring-boot-starter-test
        test
    

    
        org.springframework.boot
        spring-boot-starter
    
    
        com.alibaba
        fastjson
        ${fastjson.versino}
    

    
    
        org.projectlombok
        lombok
        true
    

    
    
        com.baomidou
        mybatis-plus-generator
        3.0.3
    
    
        com.baomidou
        mybatis-plus-boot-starter
        3.0.3
    

    
    
        org.springframework.boot
        spring-boot-starter-jdbc
    
    
        mysql
        mysql-connector-java
        ${mysql.version}
    
    

注意

引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 MyBatis-Spring,以避免因版本差异导致的问题。
如果springboot版本是SNAPSHOT快照版还需要添加仓库

    snapshots
    https://oss.sonatype.org/content/repositories/snapshots/

123456

applicaiton.yml配置

# DataSource Config
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://******:3306/crm
    username: ****
    password: ****

数据库连接换成自己的就可以

在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹

/**
 * @author hzh
 * @since 2020-08-07
 */
package com.lqf.springbootmybatisplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.lqf.springbootmybatisplus.dao.mapper")
public class SpringbootMybatisPlusApplication {

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

@MapperScan()内容填写你自己的mapper位置

对应数据库实体类编写

/**
 * @author hzh
 * @since 2020-08-07
 */
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

@Data注解会给此类默认提供Getter,Setter,equals,hashCode,toString方法
123456789

编写Mapper类 UserMapper.java

/**
 * @author hzh
 * @since 2020-08-07
 */
 @Mapper
public interface UserMapper extends BaseMapper {

}

测试类

package com.lqf.springbootmybatisplus;

import com.lqf.springbootmybatisplus.dao.mapper.UserMapper;
import com.lqf.springbootmybatisplus.domain.entity.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

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

}

测试结果

----- selectAll method test ------
User(id=1, name=Jone, age=18, [email protected])
User(id=2, name=Jack, age=20, [email protected])
User(id=3, name=Tom, age=28, [email protected])
User(id=4, name=Sandy, age=21, [email protected])
User(id=5, name=Billie, age=24, [email protected])

三 集成AutoGenerator快速搭建项目

项目搭建

pom.xml 展示



    4.0.0

    com.lqf
    springboot-mybatis-plus-genrator
    0.0.1-SNAPSHOT
    jar

    springboot-mybatis-plus-genrator
    Demo project for Spring Boot

    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.5.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-freemarker
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.projectlombok
            lombok
            true
        
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.0.3
        
        
            mysql
            mysql-connector-java
            runtime
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    




mybatis-plus.properties展示(自动生成的位置做成了配置)

#此处为本项目src所在路径(代码生成器输出路径)
OutputDir=D:/V/springboot-mybatis-plus-genrator/src/main/java
#mapper.xml的生成位置
OutputDirXml=D:/V/springboot-mybatis-plus-genrator/src/main/resources
#数据库表名(此处切不可为空,如果为空,则默认读取数据库的所有表名)
tableName=user,test1,test2
#装代码的文件夹名
className=crm
#设置作者
author=hzh
#正常情况下,下面的代码无需修改!!!!!!!!!!
#自定义包路径
parent=com.lqf.springbootmybatisplusgenrator
#数据库地址
url=jdbc:mysql://******:3306/crm?useUnicode=true&characterEncoding=utf-8&tinyInt1isBit=false
userName=***
password=***

代码生成器的java类

package com.lqf.springbootmybatisplusgenrator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

/**
 * 

* 代码生成器 *

*/ /** * @author hzh * @since 2020-08-07 */ public class MpGenerator { public static void main(String[] args) throws InterruptedException { //用来获取Mybatis-Plus.properties文件的配置信息 final ResourceBundle rb = ResourceBundle.getBundle("mybatis-plus"); // 代码生成器 AutoGenerator mpg = new AutoGenerator(); // 全局配置 GlobalConfig gc = new GlobalConfig(); gc.setOutputDir(rb.getString("OutputDir")); gc.setOpen(false); gc.setBaseResultMap(true); gc.setBaseColumnList(true); gc.setAuthor(rb.getString("author")); gc.setMapperName("%sMapper"); gc.setXmlName("%sMapper"); gc.setServiceName("%sService"); gc.setServiceImplName("%sServiceImpl"); gc.setControllerName("%sController"); mpg.setGlobalConfig(gc); // 数据源配置 DataSourceConfig dsc = new DataSourceConfig(); dsc.setDbType(DbType.MYSQL); dsc.setUrl(rb.getString("url")); dsc.setDriverName("com.mysql.jdbc.Driver"); dsc.setUsername(rb.getString("userName")); dsc.setPassword(rb.getString("password")); mpg.setDataSource(dsc); // 包配置 PackageConfig pc = new PackageConfig(); pc.setParent(rb.getString("parent")); pc.setController("controller." + rb.getString("className")); pc.setService("service." + rb.getString("className")); pc.setServiceImpl("service." + rb.getString("className") + ".impl"); pc.setEntity("bean." + rb.getString("className")); pc.setMapper("dao." + rb.getString("className")); mpg.setPackageInfo(pc); // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; List focList = new ArrayList<>(); focList.add(new FileOutConfig("/templates/mapper.xml.ftl") { @Override public String outputFile(TableInfo tableInfo) { // 自定义输入文件名称 return rb.getString("OutputDirXml") + "/mapper/" + rb.getString("className") + "/" + tableInfo.getEntityName() + StringPool.DOT_XML; } }); cfg.setFileOutConfigList(focList); mpg.setCfg(cfg); mpg.setTemplate(new TemplateConfig().setXml(null)); // 策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); //表的名字,在配置中以,给给, strategy.setInclude(rb.getString("tableName").split(",")); mpg.setStrategy(strategy); mpg.setTemplateEngine(new FreemarkerTemplateEngine()); mpg.execute(); } }

上方代码中有很多的配置,想了解配置含义的请查看官方解析

到这里为止你就可以自动生成一整套的 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码。

下面开始介绍不同系列的坑

坑1 (错误日志)

==========================准备生成文件...==========================
Exception in thread "main" java.lang.NoClassDefFoundError: freemarker/template/Configuration
	at com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine.init(FreemarkerTemplateEngine.java:45)
	at com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine.init(FreemarkerTemplateEngine.java:38)
	at com.baomidou.mybatisplus.generator.AutoGenerator.execute(AutoGenerator.java:98)
	at com.lqf.springbootmybatisplusgenrator.MpGenerator.main(MpGenerator.java:91)
Caused by: java.lang.ClassNotFoundException: freemarker.template.Configuration
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 4 more

Process finished with exit code 1
123456789101112131415

看上面的错误java.lang.NoClassDefFoundError: freemarker/template/Configuration
问题是找不到freemarker/template/Configuration这是怎么引起的呢

注意: freemarker我们那里用到了 ,看下面的代码

 focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输入文件名称
                return rb.getString("OutputDirXml") + "/mapper/" + rb.getString("className") + "/" + tableInfo.getEntityName() + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
12345678

我们在使用new FileOutConfig("/templates/mapper.xml.ftl") 生成模板的时候是需要依赖freemarker包所以我们需要在pom文件中引入

 
            org.springframework.boot
            spring-boot-starter-freemarker
        
1234

这里是官方文档没有介绍到的,坑1

坑2

字段类型为 bit、tinyint(1) 时映射为 boolean 类型这个时候MyBatis 是不会自动处理该映射的需要修改请求连接添加参数 tinyInt1isBit=false如下

jdbc:mysql://127.0.0.1:3306/mp?tinyInt1isBit=false
1

否则会报很多类型转换 boolean的错误

记得生成成功之后,在测试运行的时候要在主启动类上添加@MapperScan(value = “”)哦。

欢迎大家的指正和探讨,

四 mybatis plus详细拆解CRUD

注明 : 本篇文章将介绍springboot+mybatis-plus通过AutoGenerator自动生成entrty、controller、service、dao、mapper后对于基本的CRUD的操作和注意事项。

初始化项目搭建

层级代码展示

衡云blog系列--2.集成篇,springboot集成mybatis-plus及generate_第2张图片

上图为自动生成后的层级展示,那么下面就开始我们的测试之路

在测试之前我们需要注意一些要点,如下放代码所示我们需要在yml配置文件中加入下面的代码块。这样在我们测试的时候会在控制台打印sql语句供我们参考

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

实例测试

 /**
     * 

* insert 插入测试 *

*/ @Test public void insertLoads() { User user = new User(); user.setEmail("[email protected]"); user.setAge(12); Integer insert = mapper.insert(user); System.out.println("return insert value = " + insert); } 1234567891011121314

sql执行和打印结果

==>  Preparing: INSERT INTO user ( id, age, email ) VALUES ( ?, ?, ? ) 
==> Parameters: 1046280811781570561(Long), 12(Integer), [email protected](String)
<==    Updates: 1
return insert value = 1
1234

上面的结果我们可以看到inset操作正常添加了,插入的也只有三个字段,其他没有填写的字段是不会添加,在看自动生成的id是一个Long类型的设置。这里需要注意的是如果你想要一个主键自增的id那么你需要进行id主键自增的设置

   @TableId(value = "id", type = IdType.AUTO)
    private Long id;
12

IdType.AUTO这个就是主键自增的标识,如果你在创建数据表的时候设置了主键自增在自动生成的时候注解就会自动添加的。在2.X的版本中还存在insertAllColumn现在的3.0版本已经不存在了就不做介绍了。

/**
     *

* 通过id更新信息 *

*/ @Test public void updateByIdLoads() { User user = new User(); user.setAge(123); user.setEmail("[email protected]"); user.setId(1L); Integer insert = mapper.updateById(user); System.out.println("return insert value = " + insert); } 123456789101112131415

sql执行和打印结果

==>  Preparing: UPDATE user SET age=?, email=? WHERE id=? 
==> Parameters: 123(Integer), [email protected](String), 1(Long)
<==    Updates: 1
return insert value = 1
1234

这里我就不多说了相信大家都懂

/**
     * 

* deleteBatchIds 根据id批量删除 *

*/ @Test public void deleteLoads() { List list = new ArrayList<>(); list.add(1L); list.add(2L); list.add(3L); Integer insert = mapper.deleteBatchIds(list); System.out.println("return deleteBatchIds value = " + insert); } 123456789101112131415

sql执行和打印结果

==>  Preparing: DELETE FROM user WHERE id IN ( ? , ? , ? ) 
==> Parameters: 1(Long), 2(Long), 3(Long)
<==    Updates: 3
return deleteBatchIds value = 3
1234

看上面的结果可以看出批量删除的操作其实是id in返回结构是删除成功的条数

  /**
     * 

* deleteById 根据id删除 *

*/ @Test public void deleteByIdLoads() { Integer deleteById = mapper.deleteById(4L); System.out.println("return deleteById value = " + deleteById); } 12345678910

这个就是通过id删除一条数据

/**
     * 

* deleteByMap 根据map条件进行删除 *

*/ @Test public void deleteByMapsLoads() { HashMap map = new HashMap<>(16); map.put("email", "[email protected]"); map.put("age", 12); Integer insert = mapper.deleteByMap(map); System.out.println("return deleteByMap value = " + insert); } 1234567891011121314

这个就是通过map条件进行删除操作,条件查询到多少条删除多少,这里需要注意的是,map中的key对应的是数据库字段例如数据库user_id,实体类是userId这是在作为map key的时候需要填写user_id。

sql执行和打印结果

==>  Preparing: DELETE FROM user WHERE email = ? AND age = ? 
==> Parameters: [email protected](String), 12(Integer)
<==    Updates: 6
return deleteByMap value = 6
1234
 /**
     * 

* 通过id查询对象 *

*/ @Test public void selectByIdLoads() { User user = mapper.selectById(4L); System.out.println("return insert value = " + user); } 12345678910

这里是通过id进行查询返回单个实体对象

/**
     * 

* 通过多个id进行查询 *

*/ @Test public void selectBatchIdsLoads() { List list = new ArrayList<>(); list.add(1L); list.add(2L); list.add(3L); List list1 = mapper.selectBatchIds(list); System.out.println("return selectBatchIds value = " + list1); } 1234567891011121314

通过多个id进行查询返回list集合

/**
     * 

* 通过条件进行实体list查询 *

*/ @Test public void selectByMapLoads() { HashMap map = new HashMap<>(16); map.put("email", "[email protected]"); map.put("age", 12); List list = mapper.selectByMap(map); System.out.println("return selectByMap value = " + list); } 12345678910111213

通过多个条件进行实体list查询

 /**
     * 

* 分页查询 *

*/ @Test public void selectPageLoads() { Page page = new Page<>(1,5); IPage lstUser = mapper.selectPage(page, null); System.out.println("return selectPageLoads value = " + lstUser); } 123456789101112

上面的查询是分页查询,page中的1代表当前页,5代表每页条数。要想实现mybatis-plus分页首先需要确定配置了分页插件配置方法如下,null代表的是条件构造器这个我在后面会讲,

/**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
1234567

在配置类或启动类中增加上面的bean就可以使用了,如不不添加分页不成功查询所有内容

分页后sql打印


上方的所有测试就是springboot + mybatis-plus自动生成后的所有简单CRUD操作查询。

我们来看一下mapper中的BaseMapper<>源码

/*
 * Copyright (c) 2011-2020, hubin ([email protected]).
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.baomidou.mybatisplus.core.mapper; import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Param; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Constants; /** *

* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能 *

*

* 这个 Mapper 支持 id 泛型 *

* * @author hubin * @since 2016-01-23 */ public interface BaseMapper { /** *

* 插入一条记录 *

* * @param entity 实体对象 */ int insert(T entity); /** *

* 根据 ID 删除 *

* * @param id 主键ID */ int deleteById(Serializable id); /** *

* 根据 columnMap 条件,删除记录 *

* * @param columnMap 表字段 map 对象 */ int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap); /** *

* 根据 entity 条件,删除记录 *

* * @param queryWrapper 实体对象封装操作类(可以为 null) */ int delete(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** *

* 删除(根据ID 批量删除) *

* * @param idList 主键ID列表(不能为 null 以及 empty) */ int deleteBatchIds(@Param(Constants.COLLECTION) Collection idList); /** *

* 根据 ID 修改 *

* * @param entity 实体对象 */ int updateById(@Param(Constants.ENTITY) T entity); /** *

* 根据 whereEntity 条件,更新记录 *

* * @param entity 实体对象 (set 条件值,不能为 null) * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper); /** *

* 根据 ID 查询 *

* * @param id 主键ID */ T selectById(Serializable id); /** *

* 查询(根据ID 批量查询) *

* * @param idList 主键ID列表(不能为 null 以及 empty) */ List selectBatchIds(@Param(Constants.COLLECTION) Collection idList); /** *

* 查询(根据 columnMap 条件) *

* * @param columnMap 表字段 map 对象 */ List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap); /** *

* 根据 entity 条件,查询一条记录 *

* * @param queryWrapper 实体对象 */ T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** *

* 根据 Wrapper 条件,查询总记录数 *

* * @param queryWrapper 实体对象 */ Integer selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** *

* 根据 entity 条件,查询全部记录 *

* * @param queryWrapper 实体对象封装操作类(可以为 null) */ List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** *

* 根据 Wrapper 条件,查询全部记录 *

* * @param queryWrapper 实体对象封装操作类(可以为 null) */ List> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** *

* 根据 Wrapper 条件,查询全部记录 * 注意: 只返回第一个字段的值 *

* * @param queryWrapper 实体对象封装操作类(可以为 null) */ List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** *

* 根据 entity 条件,查询全部记录(并翻页) *

* * @param page 分页查询条件(可以为 RowBounds.DEFAULT) * @param queryWrapper 实体对象封装操作类(可以为 null) */ IPage selectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); /** *

* 根据 Wrapper 条件,查询全部记录(并翻页) *

* * @param page 分页查询条件 * @param queryWrapper 实体对象封装操作类 */ IPage> selectMapsPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); } 9

通过看上面的baseMapper大家肯定会说你里面有很多没有说啊!是的,在这里介绍的都是基本的CRUD没有涉及到条件构造器的,我将在下篇为大家详细的讲解条件构造器,并将上面没有说到的方法一并解决。

五 条件构造器queryWrapper、updateWrapper

一、条件构造器关系介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xu1wTaEH-1596892317090)(D:\Typora\java核心\框架\mybatis-plus\assets\20181001173726837.png)]

介绍 :

  1. 上图绿色框为抽象类abstract
  2. 蓝色框为正常class类,可new对象
  3. 黄色箭头指向为父子类关系,箭头指向为父类

wapper介绍 :

  1. Wrapper : 条件构造抽象类,最顶端父类,抽象类中提供4个方法西面贴源码展示
  2. AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
  3. AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
  4. LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
  5. LambdaUpdateWrapper : Lambda 更新封装Wrapper
  6. QueryWrapper : Entity 对象封装操作类,不是用lambda语法
  7. UpdateWrapper : Update 条件封装,用于Entity对象更新操作

二、项目实例

在这里我以QueryWrapper和UpdateWrapper为例,进行测试讲解。我会在上篇博客原有的基础上进行测试,如果不喜欢搭建项目的可直接下载我上个项目,上个项目的博客对应上个项目的讲解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5yuuKDmh-1596892317093)(D:\Typora\java核心\框架\mybatis-plus\assets\20181001202710403.png)]

上图表格为条件构造器使用中的各个方法格式和说明,如有不懂可参考官方文档内容

构造器条件

package com.lqf.crud;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lqf.crud.bean.crm.User;
import com.lqf.crud.dao.crm.UserMapper;
import com.sun.org.apache.xerces.internal.util.EntityResolverWrapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.RowBounds;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.jsf.el.WebApplicationContextFacesELResolver;

import javax.naming.Name;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RunWith(SpringRunner.class)
@SpringBootTest
public class QueryWrapperTests {

    @Autowired
    private UserMapper mapper;

    /**
     * 

* 根据根据 entity 条件,删除记录,QueryWrapper实体对象封装操作类(可以为 null) * 下方获取到queryWrapper后删除的查询条件为name字段为null的and年龄大于等于12的and email字段不为null的 * 同理写法条件添加的方式就不做过多介绍了。 *

*/ @Test public void delete() { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper .isNull("name") .ge("age", 12) .isNotNull("email"); int delete = mapper.delete(queryWrapper); System.out.println("delete return count = " + delete); } /** *

* 根据 entity 条件,查询一条记录, * 这里和上方删除构造条件一样,只是seletOne返回的是一条实体记录,当出现多条时会报错 *

*/ @Test public void selectOne() { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "lqf"); User user = mapper.selectOne(queryWrapper); System.out.println(user); } /** *

* 根据 Wrapper 条件,查询总记录数 *

* * @param queryWrapper 实体对象 */ @Test public void selectCount() { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "lqf"); Integer count = mapper.selectCount(queryWrapper); System.out.println(count); } /** *

* 根据 entity 条件,查询全部记录 *

* * @param queryWrapper 实体对象封装操作类(可以为 null)为null查询全部 */ @Test public void selectList() { List list = mapper.selectList(null); System.out.println(list); } /** *

* 根据 Wrapper 条件,查询全部记录 *

* * @param queryWrapper 实体对象封装操作类(可以为 null) */ @Test public void selectMaps() { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.isNotNull("name"); List> maps = mapper.selectMaps(queryWrapper); for (Map map : maps) { System.out.println(map); } } /** * 打印结果 * {name=lqf, id=1046282328366391406, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391407, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391408, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391409, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391410, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391411, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391412, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391413, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391414, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391415, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391416, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391417, age=12, [email protected], status=false} * {name=lqf, id=1046282328366391418, age=12, [email protected], status=false} * json类型的键值对模式 */ /** *

* 根据 entity 条件,查询全部记录(并翻页) *

* * @param page 分页查询条件(可以为 RowBounds.DEFAULT) * @param queryWrapper 实体对象封装操作类(可以为 null) */ @Test public void selectPage() { Page page = new Page<>(1, 5); QueryWrapper queryWrapper = new QueryWrapper<>(); IPage userIPage = mapper.selectPage(page, queryWrapper); System.out.println(userIPage); } /** * 打印结果 * ==> Preparing: SELECT COUNT(1) FROM user * ==> Parameters: * <== Columns: COUNT(1) * <== Row: 100 * ==> Preparing: SELECT id,name,age,email,status FROM user LIMIT 0,5 * ==> Parameters: * <== Columns: id, name, age, email, status * <== Row: 1046282328366391319, lqf, 12, [email protected], 0 * <== Row: 1046282328366391320, lqf, 12, [email protected], 0 * <== Row: 1046282328366391321, lqf, 12, [email protected], 0 * <== Row: 1046282328366391322, lqf, 12, [email protected], 0 * <== Row: 1046282328366391323, lqf, 12, [email protected], 0 * <== Total: 5 * * * 这里需要在项目中加入分页插件 * @Bean * public PaginationInterceptor paginationInterceptor() { * return new PaginationInterceptor(); * } */ /** *

* 根据 Wrapper 条件,查询全部记录(并翻页) *

* * @param page 分页查询条件 * @param queryWrapper 实体对象封装操作类 */ @Test public void selectMapsPage() { Page page = new Page<>(1, 5); QueryWrapper queryWrapper = new QueryWrapper<>(); IPage> mapIPage = mapper.selectMapsPage(page, queryWrapper); System.out.println(mapIPage); } /** * 和上个分页同理只是返回类型不同 */ /** *

* 根据 whereEntity 条件,更新记录 *

* * @param entity 实体对象 (set 条件值,不能为 null) * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ @Test public void update() { //修改值 User user = new User(); user.setStatus(true); user.setName("zhangsan"); //修改条件s UpdateWrapper userUpdateWrapper = new UpdateWrapper<>(); userUpdateWrapper.eq("name", "lqf"); int update = mapper.update(user, userUpdateWrapper); System.out.println(update); } /** * 打印结果 * ==> Preparing: UPDATE user SET name=?, status=? WHERE name = ? * ==> Parameters: zhangsan(String), true(Boolean), lqf(String) * <== Updates: 100 * Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@56a4f272] * 100 * 2018-10-02 15:08:03.928 INFO 7972 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@37313c65: startup date [Tue Oct 02 15:08:00 CST 2018]; root of context hierarchy * 2018-10-02 15:08:03.937 INFO 7972 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... * 2018-10-02 15:08:04.053 INFO 7972 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. * * Process finished with exit code 0 */ }

上方代码对通过构造器条件进行的查询、删除、修改进行是演示,构造器方法没有做过多演示,但是所有的构造器方法同理使用,如果还有不会用的点开看官方文档查看并按照上方例子使用即可。

你可能感兴趣的:(衡云blog系列,spring,boot,mybatis-plus)