【SpringBoot框架篇】14.mybatis-plus实战

文章目录

  • 简介
  • 版本
  • 使用模板生成器生成模板代码
    • 添加依赖
    • 创建表
    • 创建模板实体类的超类
    • 添加模板生成器代码
    • 运行main函数
  • 使用mybatis-plus实现基本的CRUD功能
    • 通用代码层
      • service代码详解
      • mapper
    • 控制器层调用接口
    • 自定义分页条件注入器
    • 页面查询条件注入代码
    • 配套代码已上传到github上
  • 项目配套代码

简介

Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。这是官方给的定义,关于mybatis-plus的更多介绍及特性,可以参考mybatis-plus官网。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA。

官网地址: https://mybatis.plus/guide/

版本

  • springboot版本是: 2.3.0.RELEASE
  • mybatis-plus-boot-starter的使用的 3.3.2

使用模板生成器生成模板代码

添加依赖

   
        1.8
        3.3.2
    
    
      
       
        
            com.baomidou
            mybatis-plus-boot-starter
            ${mybatis-plus.version}
        

        
        
            com.baomidou
            mybatis-plus-generator
            ${mybatis-plus.version}
        

        
        
            org.springframework.boot
            spring-boot-starter-freemarker
        
        
        
        
            org.projectlombok
            lombok
        
   
    

创建表

CREATE TABLE sys_user (
id int  AUTO_INCREMENT,
username varchar(20) COMMENT '用户名',
password varchar(20) COMMENT '密码',
create_time datetime COMMENT '创建时间',
grade   int COMMENT '年纪',
 PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建模板实体类的超类

通常会把一些通用的字段放入到超类中

@Data
public class BaseEntity {

    private Integer id;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

}

添加模板生成器代码

public class MysqlGenerator {

    //生成类的作者描述
    private final static String AUTHOR="LeeJunMing";
    private final static String DATASOURCE_URL="jdbc:mysql://localhost:3306/boot_master?useSSL=false&serverTimezone=GMT%2b8&characterEncoding=utf8&connectTimeout=10000&socketTimeout=3000&autoReconnect=true";
    private final static String DATASOURCE_DRIVER_NAME="com.mysql.cj.jdbc.Driver";
    private final static String DATASOURCE_USERNAME="root";
    private final static String DATASOURCE_PASSWORD="123456";
    //基础包名
    private final static String BASE_PACKAGE="com.ljm.boot";
    //生成的模块名称
    private final static String MODEL_NAME="mybatisplus";
    //超类的字段(不会出现在自动生成的表中)
    private final static String[] SUERP_COLUMN=new String[]{"id","create_time"};
    //要把哪些表生成模板代码
    private final static String [] GENERATOR_TABLES=new String[]{"sys_user"};

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        //聚合工程需要写工程的名字,普通工程写 '' 就行
        String parantPath="/14_mybatis-plus";
        gc.setOutputDir(projectPath + parantPath+"/src/main/java");
        gc.setAuthor(AUTHOR);
        gc.setOpen(false);
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(DATASOURCE_URL);
        dsc.setDriverName(DATASOURCE_DRIVER_NAME);
        dsc.setUsername(DATASOURCE_USERNAME);
        dsc.setPassword(DATASOURCE_PASSWORD);
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(MODEL_NAME);
        pc.setParent(BASE_PACKAGE);
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输入文件名称
                return projectPath + parantPath+"/src/main/java/"+BASE_PACKAGE.replaceAll("\\.","/")+"/" + pc.getModuleName()
                        + "/mapper/xml/" + tableInfo.getEntityName() + "Mapper" + 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.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController");

        //设置实体类的超类
        strategy.setSuperEntityClass(BaseEntity.class);
        //设置
        strategy.setInclude(GENERATOR_TABLES);
        strategy.setSuperEntityColumns(SUERP_COLUMN);
        strategy.setControllerMappingHyphenStyle(true);
        mpg.setStrategy(strategy);

        // 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

}

运行main函数

看到下面的日志就代表模板文件生成成功了.
在这里插入图片描述
会把每个表生成一个controller->service->mapper>xml>entity
生成的结构如下
【SpringBoot框架篇】14.mybatis-plus实战_第1张图片

使用mybatis-plus实现基本的CRUD功能

通用代码层

下面的代码会在模板生成器生成模板的时候会自动添加上

service代码详解

此处继承了ServiceImpl通用代码实现类

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

}

查看ServiceImpl 源码能看到已经定义了一些通用的代码

//新增  这个有点迷,我以为会和Jpa一样自动判断添加和修改,这个save只能添加
boolean save(T entity);

//根据id获取
T getById(Serializable id)

//根据条件查询
List<T> list(Wrapper<T> queryWrapper)

//分页查询
<E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper);

//批量新增 (默认是1000条,可以调用saveBatch(Collection entityList, int batchSize)指定批量操作数量)
boolean saveBatch(Collection<T> entityList)

//添加或者修改
boolean saveOrUpdate(T entity);

//批量添加或者修改
boolean saveOrUpdateBatch(Collection<T> entityList)

//根据ID删除
removeById(Serializable id)

//根据Id批量删除
boolean removeByIds(Collection<? extends Serializable> idList)


mapper

此处继承BaseMappe 接口

public interface SysUserMapper extends BaseMapper<SysUser> {

}

控制器层调用接口

接口采用了RESTful风格

@Controller
@RequestMapping("/user")
public class SysUserController {

    @Autowired
    ISysUserService userService;

    /**
     * 分页查询
     */
    @GetMapping("/")
    public String getUserBypage(PageParam<SysUser> pageParam, Model model) {
        pageParam.initialization();
        IPage<SysUser> iPage = userService.page(pageParam.getPage(), pageParam.getQueryWrapper());
        System.out.printf("总页数:{%d},总记录数:{%d}", iPage.getPages(), iPage.getTotal());
        model.addAttribute("page", new PageResult<>(iPage));
        return "user/index";
    }

    /**
     * ajax 分页查询
     */
    @PostMapping(value = "/json")
    @ResponseBody
    public PageResult getUserJsonDataBypage(@RequestBody PageParam<SysUser> pageParam, Model model) {
        pageParam.initialization();
        IPage<SysUser> iPage = userService.page(pageParam.getPage(), pageParam.getQueryWrapper());
        model.addAttribute("page", new PageResult<>(iPage));
        return new PageResult<>(iPage);
    }


    /**
     * 根据id获取user,并且跳转到数据修改页面
     */
    @GetMapping("/{id}")
    public String getUserById(@PathVariable Integer id, Model model) {
        //id=-1的时候代表着是重添加用户按钮进来的请求
        if (id != -1) {
            SysUser user = userService.getById(id);
            model.addAttribute("user", user);
        }
        return "user/save";
    }


    /**
     * 添加用户
     */
    @PostMapping("/")
    @ResponseBody
    public boolean addUser(SysUser user) {
        return userService.save(user);
    }

    /**
     * 修改用户
     */
    @PutMapping("/")
    @ResponseBody
    public boolean modifyUser(SysUser user) {
        return userService.saveOrUpdate(user);
    }

    /**
     * 删除
     */
    @DeleteMapping("/{ids}")
    @ResponseBody
    public boolean deleteUserById(@PathVariable String ids) {
        String idarr[] = ids.split(",");
        if (idarr.length == 1) {
            return  userService.removeById(idarr[0]);
        } else {
            return userService.removeByIds(Arrays.asList(idarr));
        }
    }

}

自定义分页条件注入器

@Data
public class PageParam<T>  {

    private Integer DEFAULT_PAGE_SIZE=10;

    private Page<T> page;

    //查询条件构造器
    private QueryWrapper<T> queryWrapper;

    private Integer currentPage;

    private Integer pageSize;

    @JsonFormat(pattern="yyyy-MM-dd",timezone="Asia/Shanghai")
    private Date beginDate;

    @JsonFormat(pattern="yyyy-MM-dd",timezone="Asia/Shanghai")
    private Date endDate;

    private Map<String, Object> eq = new HashMap<>();

    private Map<String, String> like = new HashMap<>();

    /**
     * 构建jpa需要的分页对象 初始化
     */
    public  void initialization() {
        if(this.currentPage==null){
            this.currentPage=1;
        }
        if(this.pageSize==null){
            this.pageSize=this.DEFAULT_PAGE_SIZE;
        }
        this.page= new Page<>(this.currentPage, this.pageSize);
        this.setCompare();
    }


    /**
     * 注入查询条件参数
     */
    private void setCompare() {
        this.queryWrapper=new QueryWrapper<>();
        if (!StringUtils.isEmpty(beginDate)) {
            //大于或等于传入时间
            queryWrapper.ge("create_time",beginDate);
        }
        if (!StringUtils.isEmpty(endDate)) {
            //小于或等于传入时间
            queryWrapper.le("create_time",beginDate);
        }

        String value = "";
        //注入文本框的模糊查询参数
        for (Map.Entry<String, String> entry : like.entrySet()) {
            value = entry.getValue().trim();
            if (StringUtils.isEmpty(value)) {
                continue;
            }
            //过滤掉非法的符号,不然会影响模糊查询
            value = value.replaceAll("%", "////%").replaceAll("_", "////_");
            queryWrapper.like(entry.getKey(),  value );
        }

        //注入下拉框或单选框的等值查询参数
        for (Map.Entry<String, Object> entry : eq.entrySet()) {
            if (StringUtils.isEmpty(entry.getValue())) {
                continue;
            }
            queryWrapper.eq(entry.getKey(),entry.getValue());
        }
    }
}

页面查询条件注入代码

util.getFromData=function(form) {
    var root={}
    var like={};
    var eq={};

    //注入页码和当前页
    root["currentPage"]=$("[name='currentPage']").val();
    root["pageSize"]=$("[name='pageSize']").val();

    //文本框都用模糊查询
    form.find("[type='text']").each(function(){
        var value= $(this).val();      //input 值
        var name= $(this).attr('name');
        if(name.indexOf("Date")!=-1){
            //日期字段用root注入
            root[name]=value;
        }else{
            //其它文本字段注入到like参数中
            like[name]=value;
        }
    });

    //单选框 等值匹配
    form.find("[type='radio']:checked").each(function(){
        var value= $(this).val();      //input 值
        var name= $(this).attr('name');
        eq[name]=value;
    });

    //等值匹配
    form.find("select").each(function(){
        var value= $(this).val();
        var name= $(this).attr('name');
        //页码信息是用select装的,所有排除掉
        if(name!="pageSize"){
            eq[name]=value;
        }
    });

    root['eq']=eq;
    root['like']=like;
    return root;
}

var $form=$("form");
$.ajax({
        type: 'post',
        url: url,
        data: JSON.stringify(util.getFromData($form)),
        contentType: "application/json",
        success: function (page){
        
		}, 
        error:function () {
            layer.msg("网络异常!", {icon: 2, time: 2000});
        }
    });

配套代码已上传到github上

github地址: https://github.com/Dominick-Li/springboot-master

该demo已经实现了简单的CRUD+分页查询功能
由于生成模板需要用的freemarker模板引擎,所以页面的数据渲染也使用的freemarker模板引擎渲染
页面的ui库使用的h-ui,官网地址:http://www.h-ui.net/
【SpringBoot框架篇】14.mybatis-plus实战_第2张图片

项目配套代码

github地址
要是觉得我写的对你有点帮助的话,麻烦在github上帮我点 Star

【SpringBoot框架篇】其它文章如下,后续会继续更新。

  • 1.搭建第一个springboot项目
  • 2.Thymeleaf模板引擎实战
  • 3.优化代码,让代码更简洁高效
  • 4.集成jta-atomikos实现分布式事务
  • 5.分布式锁的实现方式
  • 6.docker部署,并挂载配置文件到宿主机上面
  • 7.项目发布到生产环境
  • 8.搭建自己的spring-boot-starter
  • 9.dobbo入门实战
  • 10.API接口限流实战
  • 11.Spring Data Jpa实战
  • 12.使用druid的monitor工具查看sql执行性能
  • 13.使用springboot admin对springboot应用进行监控
  • 14.mybatis-plus实战

你可能感兴趣的:(springBoot)