mybatis - 通用mapper
title: 玩转spring-boot-mybatis
date: 2019-03-11 19:36:57
type: "mybatis"
categories: mybatis  #分类名
tags: mybatis
作为持久层的ORM框架,目前在国内主流之一就是MyBatis,学会用它,用好它肯定是必备的功课
我会主要从下面几个方面入整理本篇博客
- 快速搭建快发环境
- 常见的注解
- 怎么玩?
一. 快速搭建开发环境
小插曲,添加测试模块的时候,引入junit模块和spring-boot-text-starter模块有先顺序,不然ide会报错...
坐标
  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/><!-- lookup parent from repository -->
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--通用mapper启动器-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>
        <!--分页助手-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
        <!--测试-->
        <!--先添加 junit  再添加下面的text  stater-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>text</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
- 另外插一嘴---mysql连接的版本适配
我现在用的云主机docker上的官方版mysql,版本比较新,因此我的调整版本到 8以上,不然会报错说什么
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could
配置文件:
- 主要是配置数据库的连接,如果我们使用的是通用mapper,Mybatis可以做到零配置
server:
  port: 8089
spring:
  application:
    name: text-mybatis
  datasource:
    url: jdbc:mysql://211.159.XXX.XXX:8888/changwu?serverTimezone=UTC&useUnijava=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 2424zcw..
    driver-class-name: com.mysql.jdbc.Driver
#输出sql
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
启动类
- 在这里告诉通用mapper我们的mapper包路径
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@MapperScan("com.changwu.mapper")
public class MybatisApp {
    public static void main(String[] args) {
        SpringApplication.run(MybatisApp.class);
    }
}
编写Mapper
- 让我们自己的Mapper继承通用mapper,泛型是实体类名
- 给它实体类名,就相当与告诉它了我们的表里的字段,不让他怎么会知道如何动态生成sql ?
import tk.mybatis.mapper.common.Mapper;
public interface MyMapper extends Mapper<MyBrand> {}
ok,到现在环境就搭建好了
二. 常见的注解
- 这里的注解主要是作用在实体类上的注解,当我们撸起袖子写代码的时候,被给它难住喽,尴尬
情景1: 对于实体类
标记他对应那张表
import javax.persistence.Table;
@Table(name = "tb_brand")
情景2: 对于主键
大多数情况主键一般都叫id,bigint类型,没什么超级特殊的情况我们都希望他可以自己增长,下面两个注解都可以做到这件事,但是前提表id属性必须设置成 autoincreament , 不然报错说,id不能不写
- 注解1:
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/*
*  使用的是jpa的策略生成器
*JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO. 
* TABLE:使用一个特定的数据库表格来保存主键。 
* SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列
* IDENTITY:主键由数据库自动生成(主要是自动增长型) 
* AUTO:主键由程序控制。
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
- 注解2:
直接使用Mybatis的原生注解
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
情景3:
我们都知道springMVC会把前端发送过来的json转化为我们的javaBean,因此我们的javaBean里面的属性名和前端发送的那个对象的属性名要意义对应的,这是规范!
设想,加入前端一顿收集数据,把商品的品牌信息和库存信息都发送过来了,只有关于品牌的javabean,数据接受不全怎么办? 没关系,下面的注解可以搞定
- @Transient (意味短暂的)告诉mapper 他不是PO(持久层对象,Persistence Object)的属性,而且,springMvc还会把信息关于库存的信息,封装进去
@Transient
情景4:
我们的pojo属性名,和数据库中的关键字重名怎么办?
@Column() 可以解决 数据库中的字段为数据库的关键字的问题
@Column(name="`numeric`")  //
private Boolean numeric;   //是否是数字类型
情景5 :
数据表中tingint(1) 对应的javaBean的属性咋写?
tingint(1) // 它是boolean的同义词
情景5:
关于VO , 如何选择性的返回给前端javaBean的属性?就比如说我们查询有没有这个用户,总不至于把密码,私人信息一块返回给前端吧?
import com.fasterxml.jackson.annotation.JsonIgnore;
@JsonIgnore
它是jackson的注解
  <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
    </dependency>
三. 怎么玩?
下面就是介绍常用的mapper的API
一. CRUD
- 两种新增
//会有选择性的新增, 智能判断 brand里面有没有空的字段,有值,用这个值,没有值而使用数据库的默认值
insertSelective(brand) 
// 假如前端提交过来的 brand里面的数据是全的,用词方法
brandMapper.insert(brand);
- 简单查询
/**
 * 根据实体中的属性值进行查询,查询条件使用等号
 * @param record
 * @return
 */
@SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
List<T> select(T record);
/**
 * 根据实体中的属性值进行查询,查询条件使用等号
 * @param record
 * @return
 */
@SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
List<T> select(T record);
/**
 * 查询全部结果
 * @return
 */
@SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
List<T> selectAll();
/**
 * 根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号
 * @param record
 * @return
 */
@SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
T selectOne(T record);
/**
 * 根据实体中的属性查询总数,查询条件使用等号
 * @param record
 * @return
 */
@SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
int selectCount(T record);
- 简单删除
/**
 * 根据主键字段进行删除,方法参数必须包含完整的主键属性
 * @param key
 * @return
 */
@DeleteProvider(type = BaseDeleteProvider.class, method = "dynamicSQL")
int deleteByPrimaryKey(Object key);
/**
 * 根据实体属性作为条件进行删除,查询条件使用等号
 * @param record
 * @return
 */
@DeleteProvider(type = BaseDeleteProvider.class, method = "dynamicSQL")
int delete(T record);
- 如何玩修改?
修改主要用到下面这个api
/**
 * 根据主键更新属性不为null的值
 * @param record
 * @return
 */
@UpdateProvider(type = BaseUpdateProvider.class, method = "dynamicSQL")
int updateByPrimaryKeySelective(T record);
看到这个方法有没有觉得很爽?  它根据主键,修改不为null的属性,意思就是说,我们把不需要修改的地方设置为null就好了
,这样看,前面需要我们一顿整,整啥呢? 结合实际的业务逻辑,把前端给交过来的数据最新的数据放到我们的bean中直接修改,把不需要修改的属性设置为null,有属性可能需要直接删除,有的属性可能要去别的表中查询(别忘了加上事务 @Transactional )
/**
 * 根据主键更新实体全部字段,null值会被更新
 * @param record
 * @return
 */
@UpdateProvider(type = BaseUpdateProvider.class, method = "dynamicSQL")
int updateByPrimaryKey(T record);
这个方法和上面的神似
二 .分页,过滤(模糊查询),搜索
API
mapper.selectByExample(example)
参照下面原生的sql.拼接查询条件
 select * from 表名
        where name like '% X %' or  letter== 'x'
        order by  id desc
逻辑
public VO queryBrandByPage(Integer page, String key, Integer rows, String sortBy, Boolean desc) {
    //分页  -- 使用分页助手,在我们真正查询之前,调用这个下面的方法,开启分页查询,他很智能,会用mybatis的拦截器
    // 对接下来要执行查询的sql进行拦截,自动的在其后面拼接  limit语句
    PageHelper.startPage(page,rows); //当前页码,每页显示的数目
    //过滤 --key     (StringUtils用的是comment lang3 下面的)
    // 过滤条件,key是前端用户传递进来的,可能仅仅是一个 小米,  也可能是 小 ---  模糊查询
   /*   select * from tb_brand
    where name like '% X %' or  letter== 'x'
    order by  id desc
    */
    Example example = new Example(Brand.class);
    if(StringUtils.isNotBlank(key)){  //不为空,过滤
       example.createCriteria().orLike("name","%"+key+"%").andEqualTo("letter",key.toUpperCase());
      //  example.createCriteria().orLike("name","%"+key+"%").or
    }
    //排序
    if(StringUtils.isNotBlank(sortBy)) { //传递进来的排序不为空,设置我们的排序条件
        // 上面的 order by 可以帮我们生成, 但是后面的 id  desc 需要我们自己写
        // String orderByClause = "id desc" ; 写死了
        String orderByClause = sortBy + (desc ? " DESC " : " ASC ");  //坑坑坑   注意要加上 空格 不然拼接完了 就是 orderBy idASC 而不是orderBy id ASC
        example.setOrderByClause(orderByClause);
    }
    //查询 获取到list ,其实是  当前页的数据 page对象
    List<Brand> list = brandMapper.selectByExample(example);
    if (CollectionUtils.isEmpty(list)){
        throw new Exception ;
    }
   // 解析List
    PageInfo<Brand> pageInfo = new PageInfo<>(list);
    return new PageResult<Brand>(pageInfo.getTotal(),list);
}
三 .自定义sql
Mybatis只能针对单表为我们生成sql,如果我们的需求是跨表操作,比如说涉及到两张表,我们就得去mapper里面自己写sql
原生sql
select * from tb_brand b
inner join tb_category_brand cb on b.id=cb.brand_id  -- 去笛卡尔积
where cb.category_id= ? ;
mapper
?用#{id} 取代
@Select("select * from tb_brand b inner join tb_category_brand cb on b.id=cb.brand_id where cb.category_id=#{cid}")
  List<Brand>  queryBrandByCid(@Param("cid") Long cid);
四 .拓展包--批量操作
- 批量查询,批量删除
注意他的包啊!
import tk.mybatis.mapper.additional.idlist.IdListMapper;
public interface Mapper extends Mapper<Category> , IdListMapper<Category,Long> {}
/**
 * 根据主键字符串进行查询,类中只有存在一个带有@Id注解的字段
 * @param idList
 * @return
 */
@SelectProvider(type = IdListProvider.class, method = "dynamicSQL")
List<T> selectByIdList(@Param("idList") List<PK> idList);
/**
 * 根据主键字符串进行删除,类中只有存在一个带有@Id注解的字段
 * @param idList
 * @return
 */
@DeleteProvider(type = IdListProvider.class, method = "dynamicSQL")
int deleteByIdList(@Param("idList") List<PK> idList);
- 批量插入:
import tk.mybatis.mapper.additional.insert.InsertListMapper;
public interface BaseMapper<T> extends InsertListMapper<T> {}
@RegisterMapper
public interface InsertListMapper<T> {
@InsertProvider(
    type = InsertListProvider.class,
    method = "dynamicSQL"
)
int insertList(List<? extends T> var1);
}
抽取出一个baseMapper, 添加 @RegisterMapper 它才会被扫描到生效
import tk.mybatis.mapper.additional.idlist.IdListMapper;
import tk.mybatis.mapper.additional.insert.InsertListMapper;
import tk.mybatis.mapper.annotation.RegisterMapper;
import tk.mybatis.mapper.common.Mapper;
@RegisterMapper
public interface BaseMapper<T> extends IdListMapper<T,Long>,Mapper<T>, InsertListMapper<T> {
}
mybatis - 通用mapper的更多相关文章
- 值得收藏的Mybatis通用Mapper使用大全。
		引言 由于小编的记性不太好,每次在写代码的时候总是把通用mapper的方法记错,所以今天把通用mapper的常用方法做一下总结,方便以后直接查看.好了,不废话啦. 引包 <!-- 通用Mappe ... 
- SpringBoot 3.SpringBoot 整合 MyBatis 逆向工程以及 MyBatis 通用 Mapper
		一.添加所需依赖,当前完整的pom文件如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&qu ... 
- Spring boot集成 MyBatis 通用Mapper
		配置 POM文件 <parent> <groupId>org.springframework.boot</groupId> <artifactId>sp ... 
- (一 、上)搭建简单的SpringBoot + java + maven + mysql + Mybatis+通用Mapper  《附项目源码》
		最近公司一直使用 springBoot 作为后端项目框架, 也负责搭建了几个新项目的后端框架.在使用了一段时间springBoot 后,感觉写代码 比spring 更加简洁了(是非常简洁),整合工具也 ... 
- spring boot集成MyBatis 通用Mapper 使用总结
		spring boot集成MyBatis 通用Mapper 使用总结 2019年 参考资料: Spring boot集成 MyBatis 通用Mapper SpringBoot框架之通用mapper插 ... 
- springboot学习笔记:8. springboot+druid+mysql+mybatis+通用mapper+pagehelper+mybatis-generator+freemarker+layui
		前言: 开发环境:IDEA+jdk1.8+windows10 目标:使用springboot整合druid数据源+mysql+mybatis+通用mapper插件+pagehelper插件+mybat ... 
- springboot学习笔记:9.springboot+mybatis+通用mapper+多数据源
		本文承接上一篇文章:springboot学习笔记:8. springboot+druid+mysql+mybatis+通用mapper+pagehelper+mybatis-generator+fre ... 
- springboot学习笔记:11.springboot+shiro+mysql+mybatis(通用mapper)+freemarker+ztree+layui实现通用的java后台管理系统(权限管理+用户管理+菜单管理)
		一.前言 经过前10篇文章,我们已经可以快速搭建一个springboot的web项目: 今天,我们在上一节基础上继续集成shiro框架,实现一个可以通用的后台管理系统:包括用户管理,角色管理,菜单管理 ... 
- Mybatis通用Mapper介绍和使用
		Mybatis通用Mapper介绍与使用 前言 使用Mybatis的开发者,大多数都会遇到一个问题,就是要写大量的SQL在xml文件中,除了特殊的业务逻辑SQL之外,还有大量结构类似的增删改查SQL. ... 
- 【SSM 8】spring集成Mybatis通用Mapper
		上篇博客中介绍了关于Mybatis底层封装的思路问题,那么这篇博客,就介绍一下怎么引入通用的mapper插件. 备注:本项目通过maven管理 关键版本说明: spring:4.1.3.RELEASE ... 
随机推荐
- 用java实现取1-100之间的99个不重复的随机数 然后输出没有被取出的数字
			package cn.kgc.springtest2.demo1.dao; import java.util.BitSet; /** * @author * @create 2019-08-02 17 ... 
- 微信小程序那些令人眼泪汪汪的坑儿
			前言 最近做了一个麻雀虽小,五脏俱全的微信小程序项目.一看就会,一用就废的小程序.有些坑真的坑的你两眼泪汪汪.我就爱干前人栽树后人乘凉的事儿,看到文章的你,也许是同道中人,相视一笑:亦或是小程序外围人 ... 
- pickle 序列化对象
			# 序列化对象 import pickle mylist=[[1,2,3,4,5,6,7],["abc","xyz","hello"],[1 ... 
- SCRUM的三个工件
			转自:http://www.scrumcn.com/agile/scrum-knowledge-library/scrum.html#tab-id-6 Scrum 的工件以不同的方式展现工作和价值,可 ... 
- HDU-DuoXiao第二场hdu 6315 Naive Operations 线段树
			hdu 6315 题意:对于一个数列a,初始为0,每个a[ i ]对应一个b[i],只有在这个数字上加了b[i]次后,a[i]才会+1. 有q次操作,一种是个区间加1,一种是查询a的区间和. 思路:线 ... 
- codeforces 801 D. Volatile Kite(数学题)
			题目链接:http://codeforces.com/contest/801/problem/D 题意:求出一个最大值D,使得一个给定的凸多边形任意点移动范围在半径为D的圆中,都不会构成一个凹都边形. ... 
- yzoj P2343 & 洛谷 P1437 [HNOI2004]敲砖块
			题意 在一个凹槽中放置了N层砖块,最上面的一层油N块砖,从上到下每层一次减少一块砖.每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如图所示. 如果你想敲掉第i层的第j块砖的话,若i=1,你可以直接 ... 
- 【Offer】[11] 【旋转数组的最小元素】
			题目描述 思路分析 Java代码 代码链接 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4, ... 
- Docker搭建disconf环境,三部曲之三:细说搭建过程
			Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ... 
- IDEA中创建maven web项目
			本文将带你一路从IDEA中maven的配置到创建maven web项目,掌握IDEA中maven的使用. 一.IDEA中配置maven 开发中一般我们使用自己下载的maven,不使用IDEA工具自带的 ... 
