一看就会一学就废之SpringBoot整合通用Mapper以及常用方法

本文详细介绍了通用Mapper在SpringBoot项目中的使用,包括它的作用、能解决的问题、如何集成以及如何使用。通用Mapper是一个辅助Mybatis简化表单开发的组件,提供单表的增删改查功能,通过继承接口即可实现。文章还展示了创建实体类、Mapper接口、Service层和Controller层的代码示例,以及通用Mapper中常用的方法和Example的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     本文适合初次学习通用Mapper新鸟阅览,老生常谈,从三个大方向入手----是什么?能干什么?怎么用?

目录

一、通用Mapper是什么?

二、通用Mapper能干什么?

三、怎么使用通用Mapper?这里基于SpringBoot实现

   整合步骤:

通用Mapper中的常用方法:


一、通用Mapper是什么?

       简单来说,它就是个辅助mybatis极简单表开发的组件,只能算插件,还算不上框架。它不是为了替代mybatis,而是让mybatis的开发更方便----可以自动生成sql语句,方便开发人员进行ORM,提供极其方便的单表(不支持通用的多表联合查询增删改查。

二、通用Mapper能干什么?

    说到这里就不得不提一提为什么会产生通用Mapper----使用原生Mybatis遇到的问题

         1.mapper.xml文件里有大量的sql,当数据库表字段变动,配置文件就要修改

         2.分页麻烦,除了传参page、pageSize,还需要返回条目总数count

         3.数据库可移植性差:如果项目更换数据库,比如oracle-->mysql,mapper.xml中的sql要重新写

         4.批量操作,批量插入,批量更新,需要自写动态SQL使用,麻烦

     也正是因为要解决这些问题,通用Mapper就出现了----主要就用于解决单表的增删改查不需要编写SQL,不需要在DAO中增加方法,只要写好实体类,就能支持相应的增删改查方法,逻辑更清晰,结构整洁,可以按照模板化编程。也一一对应的解决了原生mybatis所存在的以上问题,具体怎么解决见下文。

      缺点:   不灵活,有些SQL难以实现

                    需要在Java代码中加入大量逻辑判断,确定模板方法的准确性

                    需要大量条件判断,如非空,或者需要手动置空,才能避免覆盖

三、怎么使用通用Mapper?这里基于SpringBoot实现

   整合步骤:

                         1.创建项目,添加依赖

                         2.创建公用Mapper接口继承通用Mapper和MySqlMapper

                         3.在配置文件application.yml中配置数据库,MyBatis等

                         4.在启动类上别忘了加扫描Mapper包

                         5.使用通用Mapper

1.创建项目,添加相关依赖

        <!--Mybatis(必须)--> 
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>
		<!--分页插件 (需要分页时使用) -->
		<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper</artifactId>
			<version>1.2.5</version>
		</dependency>
        <!--通用Mapper插件依赖(必须)-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>
        <!--lombok,简化实体类代码,需要时写-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--数据库连接依赖(必须)-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
            <scope>runtime</scope>
        </dependency>
         <!--web依赖(必须)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.创建公用创建公用Mapper接口继承通用Mapper和MySqlMapper

package com.cloudsw.base;

import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

/**
 * @Description: 公用Mapper接口
 * @Date: 2021/3/29
 * @Author lijintao
 */
@component
public interface IBaseMapper<T>  extends Mapper<T>,MySqlMapper<T> {

}

注意:mappers 是指向自定以的基础通用mapper接口,该接口不能和普通接口放在一起(不然扫描自定义mapper时会报错),推荐放在工具包里,这里要注意Mapper<T>,MySqlMapper<T>都是tk包下的,Mapper<T>提供了基础的增删改查功能,MySqlMapper<T>提供了批量新增的功能,然后使用我们去继承这个mapper就有CRUD的功能

3.在配置文件application.yml中配置数据库,MyBatis等

#端口配置
server:
  port: 8088
#jdbc配置
spring:
  datasource:
    name: clodsw-portal-dev
    url: jdbc:mysql://localhost:3306/cloudsw_portal?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&autoReconnect=true&allowPublicKeyRetrieval=true
    username: 123456
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
#mybatis配置
mybatis:
  #定义xml文件位置,不是必须的,如果需要在xml写sql请配置此选项
  mapper-locations: classpath:mapper/*.xml 
  #实体类所在包名
  type-aliases-package: com.cloudsw.dto
#通用mapper配置
mapper:
  #公用接口类路径
  mappers: com.cloudsw.base.IBaseMapper
  identity: MYSQL

4.在启动类上别忘了加扫描Mapper包

package com.cloudsw;

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

@SpringBootApplication
@MapperScan("com.cloudsw.mapper")  // 需要将继承的Mapper接口添加到Mybatis配置中
public class MapperApplication {
    public static void main(String[] args) {
        SpringApplication.run(MapperApplication.class, args);
    }
}

注:此处MapperScan为tk.mybatis.spring.annotation.MapperScan,非org.mybatis.spring.annotation.MapperScan;

 5.使用通用Mapper

   5.1  定义实体类

package com.cloudsw.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Repository;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Data //使用lombok注解,可以免写getter,setter方法
@Repository //为什么 @Repository 只能标注在 DAO 类上呢?这是因为该注解的作用不只是将类识别为Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型
@Table(name = "msg_todo")//mybatis通用接口mapper依赖JPA实体类采用JPA

public class MsgTodo implements Serializable {

    private static final long serialVersionUID=1L;

    @Id   //代表主键,如果一个类中有多个这个注解代表  联合主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //主键策略
    private Long id;

    @Column(name="name")
    private String name;

    @Column(name="receive_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date receiveTime;

    @Column(name="create_code")
    private String createCode;

    @Column(name="create_name")
    private String createName;

    @Column(name="create_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @Column(name="content")
    private String content;

    @Column(name="send_type")
    private Integer sendType;

    @Transient   //代表不是数据表中的字段,只是普通属性
    private String haha;

}

注:

实体类按照如下规则和数据库表进行转换,注解全部是JPA中的注解:

  1. 表名默认使用类名,驼峰转下划线(只对大写字母进行处理),如UserInfo默认对应的表名为user_info
  2. 表名可以使用@Table(name = "tableName")进行指定,对不符合第一条默认规则的可以通过这种方式指定表名.
  3. 字段默认和@Column一样,都会作为表字段,表字段默认为Java对象的Field名字驼峰转下划线形式.
  4. 可以使用@Column(name = "fieldName")指定不符合第3条规则的字段名
  5. 使用@Transient注解可以忽略字段,添加该注解的字段不会作为表字段使用.
  6. 建议一定是有一个@Id注解作为主键的字段,可以有多个@Id注解的字段作为联合主键.默认情况下,实体类中如果不存在包含@Id注解的字段,所有的字段都会作为主键字段进行使用(这种效率极低).
  7. 由于基本类型,如int作为实体类字段时会有默认值0,而且无法消除,所以实体类中建议不要使用基本类型.
  8. @GeneratedValue,通用Mapper还提供了序列(支持Oracle)、UUID(任意数据库,字段长度32)、主键自增(类似Mysql,Hsqldb)三种方式,其中序列和UUID可以配置多个,主键自增只能配置一个。     

              1.@GeneratedValue(generator = "JDBC"):MySql自增主键

              2.@GeneratedValue(generator = "UUID"):随机主键,可以用于任意字符串类型长度超过32位的字段

  1. @NameStyle注解,用来配置对象名/字段和表名/字段之间的转换方式,该注解优先于全局配置style,可选值:
    • normal:使用实体类名/属性名作为表名/字段名
    • camelhump:这是默认值,驼峰转换为下划线形式
    • uppercase:转换为大写
    • lowercase:转换为小写

通过使用Mapper专用的MyBatis生成器插件可以直接生成符合要求带注解的实体类。

重点强调 @Transient 注解:

      如果你的实体类中包含了不是数据库表中的字段,你需要给这个字段加上@Transient注解,这样通用Mapper在处理单表操作时就不会将标注的属性当成表字段处理!

5.2  编写自定义mapper层代码

package com.cloudsw.mapper;

import com.cloudsw.base.IBaseMapper;
import com.cloudsw.dto.MsgTodo;
import org.apache.ibatis.annotations.Mapper;

/**
 * <p>
 * 待阅信息表 Mapper 接口
 * </p>
 *
 * @author zhenlong.qu@cloudsw.cn
 * @since 2020-08-10
 */
@Mapper  //编写mapper层接口,继承实现通用Mapper
public interface MsgTodoDao extends IBaseMapper<MsgTodo> {

}

5.3 编写Service层代码

  接口类:

package com.cloudsw.service;

import com.cloudsw.base.IBaseService;
import com.cloudsw.dto.MsgTodo;

import java.util.List;

public interface IMsgTodoService{


    int deleteByPrimaryKey(Integer id);

    int insert(MsgTodo msgTodo);

    MsgTodo selectByPrimaryKey(Integer id);

    List<MsgTodo> selectAll();

    int updateByPrimaryKey(MsgTodo msgTodo);
    /**
     * 根据条件分页查询
     *
     * @param country
     * @param page
     * @param rows
     * @return
     */
    List<MsgTodo> selectByMsgTodo(MsgTodo country, int page, int rows);

实现类:

package com.cloudsw.service.impl;

import com.cloudsw.base.impl.IBaseServiceImpl;
import com.cloudsw.dto.MsgTodo;
import com.cloudsw.mapper.MsgTodoDao;
import com.cloudsw.service.IMsgTodoService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;

@Service
public class ManagerServiceImpl extends IBaseServiceImpl<MsgTodo> implements IMsgTodoService {


    @Autowired
    private MsgTodoDao msgTodoDao;

    @Override
    public int deleteByPrimaryKey(Integer id) {
        int row = msgTodoDao.deleteByPrimaryKey(id);
        return row;
    }

    @Override
    public int insert(MsgTodo msgTodo) {
        return msgTodoDao.insert(msgTodo);
    }

    @Override
    public MsgTodo selectByPrimaryKey(Integer id) {
        return msgTodoDao.selectByPrimaryKey(id);
    }

    @Override
    public List<MsgTodo> selectAll() {
        return msgTodoDao.selectAll();
    }

    @Override
    public int updateByPrimaryKey(MsgTodo msgTodo) {
        return msgTodoDao.updateByPrimaryKey(msgTodo);
    }
        @Override
    public List<MsgTodo> selectByMsgTodo(MsgTodo msgTodo, int page, int rows) {
        Example example = new Example(MsgTodo.class);
        Example.Criteria criteria = example.createCriteria();
        if (msgTodo.getId() != null) {
            criteria.andEqualTo("id", msgTodo.getId());
        }
        //分页查询
        PageHelper.startPage(page, rows);
        return selectByExample(example);
    }
}

5.4  controller层代码:

package com.cloudsw.controller;

import com.cloudsw.dto.MsgTodo;
import com.cloudsw.service.IMsgTodoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class MsgTodoController {
    @Autowired
    private IMsgTodoService iMsgTodoService;
    @PostMapping(value = "/msg/insert")
    public int insert( @RequestBody MsgTodo msgTodo) {
        return iMsgTodoService.save(msgTodo);
    }


    @DeleteMapping(value = "/msg/deleteByPrimaryKey")
    public int deleteByPrimaryKey(@RequestParam(value = "id", required = true) Integer id) {
        int row = iMsgTodoService.deleteByKey(id);
        return row;
    }


    @PostMapping(value = "/manager/updateByPrimaryKey")
    public int updateByPrimaryKey(@RequestBody MsgTodo msgTodo) {
        return iMsgTodoService.updateAll(msgTodo);
    }


    @PostMapping(value = "/msg/selectByPrimaryKey")
    public MsgTodo selectByPrimaryKey(@RequestParam(value = "id", required = true) Integer id) {
        return iMsgTodoService.selectByKey(id);
    }


    @GetMapping(value = "/msg/selectAll")
    public List<MsgTodo> selectAll() {
        List<MsgTodo> managerList = iMsgTodoService.selectByExample(null);
        return managerList;
    }
    @PostMapping (value = "/msg/selectAllByPage")
    public List<MsgTodo> selectAllByPage( @RequestParam(required = false, defaultValue = "1") int page,
                                          @RequestParam(required = false, defaultValue = "10") int rows,
                                          @RequestBody MsgTodo msgTodo) {
        List<MsgTodo> managerList = iMsgTodoService.selectByMsgTodo(msgTodo,page,rows);
        return managerList;
    }
}

通用Mapper中的常用方法:

   查询相关:   List<T>  select(T record);     //根据实体中的属性值进行查询,查询条件使用等号

                        T  selectByPrimaryKey(Object key);  //根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号

                        List<T>  selectAll();    //查询全部结果,select(null)方法能达到同样的效果

                        T  selectOne(T record);   //根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号

                        int  selectCount(T record);   //根据实体中的属性查询总数,查询条件使用等号

                        PageHelper.startPage(page, rows);   //分页查询

   添加相关:   int   insert(T record);   //保存一个实体,null的属性也会保存,不会使用数据库默认值

                        int  insertSelective(T record);  //保存一个实体,null的属性不会保存,会使用数据库默认值

    修改相关:  int  updateByPrimaryKey(T record);  //根据主键更新实体全部字段,null值会被更新

                        int  updateByPrimaryKeySelective(T record);  //根据主键更新属性不为null的值

    删除相关:  int  delete(T record);   //根据实体属性作为条件进行删除,查询条件使用等号

                        int  deleteByPrimaryKey(Object key);  //根据主键字段进行删除,方法参数必须包含完整的主键属性

     Example相关: List<T>   selectByExample(Object example);   //根据Example条件进行查询,这个查询支持通过Example类指定查询列,通过selectProperties方法指定查询列

                               int   selectCountByExample(Object example);  //根据Example条件进行查询总数

                               int   updateByExample(@Param("record") T record, @Param("example") Object example);   //根据Example条件更新实体record包含的全部属性,null值会被更新

                               int   updateByExampleSelective(@Param("record") T record, @Param("example") Object example);  //根据Example条件更新实体record包含的不是null的属性值

                               int   deleteByExample(Object example);  //根据Example条件删除数据

  Example使用方法:

       Example example = new Example(需要CRUD的类(与数据库对应实体类).class);
       Example.Criteria criteria = example.createCriteria();
       criteria.andEqualTo("id",id); // id已知  RUD判断条件

    设置条件:

          example.orderBy(字段名).asc();          // 添加升序排列条件
          example.orderBy(字段名).desc();        //  添加降序排序条件
          example. setDistinct(false);                 // 去除重复,boolean型,true为选择不重复的记录
          criteria. andIsNull(字段名);                  //  添加字段xx为null的条件
          criteria. andIsNotNull(字段名);            //  添加字段xx不为null的条件
          criteria.andEqualTo(字段名,value);     //  添加xx字段等于value条件
          criteria.andNotEqualTo(字段名,value);        //  添加xx字段不等于value条件
          criteria.andGreaterThan(字段名,value);      //  添加xx字段大于value条件
          criteria.andGreaterThanOrEqualTo(字段名,value);     //   添加xx字段大于等于vaue条件
          criteria.andLessThan(字段名,value);                          //    添加xx字段小于value条件
          criteria.andLessThanOrEqualTo(字段名,value);         //     添加xx字段小于等于value条件
          criteria.andIn(字段名,list);                                           //     添加xx字段值在List条件
          criteria. andNotIn(字段名,list);                                    //    添加xx字段值不在List条件
          criteria.andLike(字段名,“%”+value+”%”);                   //    添加xx字段值为vaue的模糊查询条件
          criteria.andNotLike(字段名,“%”+value+”%”);             //     添加xx字段值不为 value的模糊查询条件
          criteria.andBetween(字段名,value1,value2);             //     添加xx字段值在value1和value2之间条件
          criteria.andNotBetween(字段名,value1,value2);       //     添加xx字段值不在value1和value2之间条件

  

Gerrit是个用于代码审查和版本控制的工具,它的使用可以通过系列步骤来完成。以下是个简单的Gerrit使用教程: 1. 首先,你需要了解Gerrit的工作流程和权限控制。这可以通过阅读相关的文档和教程来获得大致的了解。你也可以参考些博客文章,比如【Gerrit】Gerrit工作流程及使用手册。 2. 作为管理员,你可以通过命令行对Gerrit服务器进行操作。你可以使用如下命令连接到服务器:ssh gerrit -l admin。连接成功后,你就可以对Gerrit进行各种管理操作了,比如添加普通成员。 3. 在使用Gerrit之前,你需要激活账号并生成SSH密钥。你可以在本地生成SSH密钥对,并将公钥配置到Gerrit服务器中。 4. 下载代码:在Gerrit的页面上,你可以浏览项目并进行查看。你可以使用过滤器来快速搜索你感兴趣的项目。找到你想要下载的项目后,可以点击浏览页面下的repositories进行查看。在这里,你可以选择下载代码。 5. 修改与提交:在本地进行代码修改后,你可以使用git命令将修改提交到Gerrit服务器。在提交后,Gerrit会为每次提交生成个change id,并在Gerrit中生成个review请求。 6. Gerrit页面进行代码审核并合并至远程分支:在Gerrit页面上,你可以对提交的代码进行审核。审核包括对代码质量、风格等方面的评审。如果审核通过,你可以将代码合并至远程分支。 7. 远程合并后本地需要git pull更新同步:在远程合并之后,你需要在本地使用git pull命令来更新同步。之后,你可以使用git log命令来查看更新后的代码。 以上是个简单的Gerrit使用教程,希望对你有所帮助。如果你还有其他问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值