关于通用mapper的使用

  • 1 通用Mapper简介
  • 2 通用Mapper基本原理
  • 3 通用Mapper使用
    • 0 数据库准备
    • 1 新建一个SpringBoot环境
    • 2 添加maven依赖
    • 3 添加配置文件
    • 4 添加实体类
    • 5 添加mapper接口
    • 6 添加controller控制器
    • 7 添加启动类
    • 8 测试

最近有看到通用mapper的一些新用法,记录一下通用mapper的相关使用

官方文档:

https://gitee.com/free/Mapper/wikis/Home

1 通用Mapper简介

通用 Mapper是一个可以实现任意 MyBatis 通用方法的框架,项目提供了常规的增删改查操作以及Example 相关的单表操作。通用 Mapper 是为了解决 MyBatis 使用中 90% 的基本操作,使用它可以很方便的进行开发,可以节省开发人员大量的时间。

通用Mapper可以通过Mybatis的拦截器原理,动态的帮我们实现单表的增删改查功能.

2 通用Mapper基本原理

先从通用Mapper中提供的通用方法,来查看其原理

/*** 通用Mapper接口,查询** @param <T> 不能为空* @author liuzh*/
@RegisterMapper
public interface SelectMapper<T> {/*** 根据实体中的属性值进行查询,查询条件使用等号** @param record* @return*/@SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")List<T> select(T record);}

SelectMapper接口和方法都使用的是泛型, 使用时需要指定泛型类型. 通过反射很容易得到泛型接口的类型信息

Type[] types = mapperClass.getGenericInterfaces();
Class<?> entityClass = null;
for (Type type : types) {if (type instanceof ParameterizedType) {ParameterizedType t = (ParameterizedType) type;//判断父接口是否为 SelectMapper.classif (t.getRawType() == SelectMapper.class) {//得到泛型类型entityClass = (Class<?>) t.getActualTypeArguments()[0];break;}}
}

实体类中添加的 JPA 注解只是一种映射实体和数据库表关系的手段,通过一些默认规则或者自定义注解也很容易设置这种关系,获取实体和表的对应关系后,就可以根据通用接口方法定义的功能来生成和 XML 中一样的 SQL 代码

看到注解SelectProvider上type为BaseSelectProvider.class类, 查看其类代码:

/*** BaseSelectProvider实现类,基础方法实现类** @author liuzh*/
public class BaseSelectProvider extends MapperTemplate {public BaseSelectProvider(Class<?> mapperClass, MapperHelper mapperHelper) {super(mapperClass, mapperHelper);}/*** 查询** @param ms* @return*/public String selectOne(MappedStatement ms) {Class<?> entityClass = getEntityClass(ms);//修改返回值类型为实体类型setResultType(ms, entityClass);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectAllColumns(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty()));return sql.toString();}/*** 查询** @param ms* @return*/public String select(MappedStatement ms) {Class<?> entityClass = getEntityClass(ms);//修改返回值类型为实体类型setResultType(ms, entityClass);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectAllColumns(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty()));sql.append(SqlHelper.orderByDefault(entityClass));return sql.toString();}/*** 查询** @param ms* @return*/public String selectByRowBounds(MappedStatement ms) {return select(ms);}/*** 根据主键进行查询** @param ms*/public String selectByPrimaryKey(MappedStatement ms) {final Class<?> entityClass = getEntityClass(ms);//将返回值修改为实体类型setResultType(ms, entityClass);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectAllColumns(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));sql.append(SqlHelper.wherePKColumns(entityClass));return sql.toString();}/*** 查询总数** @param ms* @return*/public String selectCount(MappedStatement ms) {Class<?> entityClass = getEntityClass(ms);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectCount(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty()));return sql.toString();}/*** 根据主键查询总数** @param ms* @return*/public String existsWithPrimaryKey(MappedStatement ms) {Class<?> entityClass = getEntityClass(ms);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectCountExists(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));sql.append(SqlHelper.wherePKColumns(entityClass));return sql.toString();}/*** 查询全部结果** @param ms* @return*/public String selectAll(MappedStatement ms) {final Class<?> entityClass = getEntityClass(ms);//修改返回值类型为实体类型setResultType(ms, entityClass);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectAllColumns(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));// 逻辑删除的未删除查询条件sql.append("<where>");sql.append(SqlHelper.whereLogicDelete(entityClass, false));sql.append("</where>");sql.append(SqlHelper.orderByDefault(entityClass));return sql.toString();}
}

在 mybatis 中,每一个方法(注解或 XML )经过处理后,最终会构造成 MappedStatement 对象.

使用@SelectProvider 这种定义,会构造成 ProviderSqlSource,ProviderSqlSource 是一种处于中间的 SqlSource,它本身不能作为最终执行时使用的 SqlSource,但是他会根据指定方法返回的 SQL 去构造一个可用于最后执行的 StaticSqlSource,StaticSqlSource的特点就是静态 SQL,支持在 SQL 中使用#{param} 方式的参数,但是不支持 <if>,<where>等标签

通用 Mapper 从这里入手,利用ProviderSqlSource 可以生成正常的 MappedStatement,在生成 MappedStatement 后,就把 ProviderSqlSource 替换掉了.

接口方法中根据ms 的 id(规范情况下是 接口名.方法名)得到接口,通过接口的泛型可以获取实体类(entityClass),根据实体和表的关系我们可以拼出 XML 方式的动态 SQL

    /*** 查询全部结果** @param ms* @return*/public String selectAll(MappedStatement ms) {final Class<?> entityClass = getEntityClass(ms);//修改返回值类型为实体类型setResultType(ms, entityClass);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectAllColumns(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));// 逻辑删除的未删除查询条件sql.append("<where>");sql.append(SqlHelper.whereLogicDelete(entityClass, false));sql.append("</where>");sql.append(SqlHelper.orderByDefault(entityClass));return sql.toString();}

拼出的 XML 形式的动态 SQL,使用 mybatis 的 XMLLanguageDriver 中的 createSqlSource 方法可以生成 SqlSource。然后使用反射用新的 SqlSource 替换ProviderSqlSource .

tk.mybatis.mapper.mapperhelper.MapperTemplate通用Mapper模板类中

    /*** 重新设置SqlSource** @param ms* @param sqlSource*/protected void setSqlSource(MappedStatement ms, SqlSource sqlSource) {MetaObject msObject = MetaObjectUtil.forObject(ms);msObject.setValue("sqlSource", sqlSource);}

3 通用Mapper使用

通用mapper提供了一些基础的增删改查的方法:

        // 1 新增// Mapper接口只提供基础的增删改查  批量新增的需要使用 MySqlMapper 接口,该接口继承自 InsertListMapper 接口userMapper.insert(new User());userMapper.insertSelective(new User());userMapper.insertList(new ArrayList<User>());// 2 修改userMapper.updateByPrimaryKey(new User());userMapper.updateByPrimaryKeySelective(new User());userMapper.updateByExample(new User(), new Example(User.class));userMapper.updateByExampleSelective(new User(), new Example(User.class));// 3 删除userMapper.delete(new User());userMapper.deleteByPrimaryKey("id");userMapper.deleteByExample(new Example(User.class));// 4 查询userMapper.selectAll();userMapper.select(new User());userMapper.selectOne(new User());userMapper.selectByExample(new Example(User.class));

0 数据库准备

-- 建表语句
CREATE TABLE `user` (`id` int NOT NULL COMMENT '主键',`username` varchar(64) DEFAULT NULL COMMENT '名称',`phone` varchar(64) DEFAULT NULL COMMENT '电话',`icon` varchar(255) DEFAULT NULL COMMENT '二进制',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';-- 添加数据
INSERT INTO `test`.`user`(`id`, `username`, `phone`, `icon`) VALUES (1, '李子柒', '77777', '李子柒的头像');
INSERT INTO `test`.`user`(`id`, `username`, `phone`, `icon`) VALUES (2, '2', '2', 'world');
INSERT INTO `test`.`user`(`id`, `username`, `phone`, `icon`) VALUES (3, '3', '3', '3333');
INSERT INTO `test`.`user`(`id`, `username`, `phone`, `icon`) VALUES (5, '5', '5', '123adb');
INSERT INTO `test`.`user`(`id`, `username`, `phone`, `icon`) VALUES (7, '5', '5', '汉字你好');

1 新建一个SpringBoot环境

2 添加maven依赖

    <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper</artifactId><version>4.1.5</version></dependency><!--mybatis和spring整合--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version></dependency><!--MySQL数据库驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></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>

3 添加配置文件

spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

4 添加实体类

@Data
@Table(name = "user")
public class User {@Idprivate String id;@Columnprivate String username;@Columnprivate String phone;@Columnprivate String icon;@Transientprivate Date queryTime = new Date();}

5 添加mapper接口

// MySqlMapper接口主要是使用批量新增功能
public interface UserMapper extends Mapper<User>, MySqlMapper<User> {}

6 添加controller控制器


@Controller
@RequestMapping("/helloworld")
public class HelloWorld {@Autowiredprivate UserMapper userMapper;@GetMapping("/queryByCondition")@ResponseBodypublic String queryByCondition(@RequestParam("keyword") String keyword) {// 使用example来实现复杂关系的查询// 1 example可以查询自己需要的字段,并设置排序规则  (可选,默认是查询所有,无排序条件)Example example = new Example(User.class);example.selectProperties("id", "phone", "icon").orderBy("id").desc();// 2 模糊查询需要自己拼百分号% (mybatis-plus不需要)example.createCriteria().andLike("username", "%" + keyword + "%").orEqualTo("phone", keyword);List<User> users = userMapper.selectByExample(example);System.out.println(users);return "<h1>Hello Wrold</h1>";}}

7 添加启动类

@MapperScan("com.cf.demo.mapper")
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

8 测试

在本地浏览器访问

http://localhost:8080/helloworld/queryByCondition?keyword=子

浏览器页面展示:

Hello Wrold

控制台展示:

[User(id=1, username=null, phone=77777, icon=李子柒的头像, queryTime=Mon Oct 25 19:25:44 CST 2021)]

关于通用mapper的使用相关推荐

  1. Mybatis之通用Mapper使用

    增加Maven依赖 <!-- mybatis 通用mapper --> <dependency><groupId>tk.mybatis</groupId> ...

  2. MyBatis 为什么需要通用 Mapper ?

    一.通用 Mapper 的用途 ? 我个人最早用 MyBatis 时,先是完全手写,然后用上了 MyBatis 代码生成器(简称为 MBG),在使用 MBG 过程中,发现一个很麻烦的问题,如果数据库字 ...

  3. Mybatis 通用 Mapper 使用 ①

    简介 官网链接:https://mapperhelper.github.io/docs/ 通用Mapper都可以极大的方便开发人员.可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方 ...

  4. MyBatis 通用Mapper 入门教程

    通用Mapper 简单教程 Mapper 项目地址: [http://git.oschina.net/free/Mapper] 本教程代码地址: [https://github.com/oakshar ...

  5. 如何使用通用Mapper

    集成方法请看上面的文档,集成后,可以继续阅读本页文档. 1. 继承通用的Mapper<T>,必须指定泛型<T> 例如下面的例子: public interface UserIn ...

  6. Mybatis通用Mapper

    极其方便的使用Mybatis单表的增删改查 项目地址:http://git.oschina.net/free/Mapper 优点? 不客气的说,使用这个通用Mapper甚至能改变你对Mybatis单表 ...

  7. SpringBoot整合Mybatis,使用通用mapper和PageHelper进行分页

    乐哉码农 上节介绍了如何整合Security,这节就说下如何再Springboot下使用持久层框架mybatis和牛人封装的通用mapper与mybatis的整合,直接进入正题吧! 1.首先引入我们需 ...

  8. 通用mapper和分类实现

    1 通用Mapper 1.1 通用Mapper介绍 1.1.1 架构设计 说明:使用了通用Mapper后,单表的增删改查操作会自动的进行维护. 问题:如何才能实现数据的通用并且是动态的? 1.2 JP ...

  9. spring boot整合mybatis+通用mapper+pagehelper分页插件

    spring boot整合mybatis+通用mapper+pagehelper分页插件 pom依赖 <?xml version="1.0" encoding="U ...

  10. 【解析】spring-boot整合通用mapper

    问题描述: Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the m ...

最新文章

  1. Ubuntu11.04 3945ABG无线网卡驱动安装
  2. VPP /什么是VPP?读这篇文章就够了
  3. 用DHCP部署WPAD:ISA2006系列之四
  4. java循环写出多个jlabel_java – 允许多个JLabel中的文本重叠
  5. 理解神经网络:神经元的概念
  6. Atitit 学科与知识领域分类门类分类法 目录 1. 学位学科门类是授予学位的学科类别。国际上大体有两种划分方法: 1 2. 三大类法 文理科 医学 1 3. 五大门类 2 4. 13门类 2 5
  7. git版本管理软件——git储藏
  8. 本科毕业论文怎么避免查重?
  9. Word排版如何快速自动生成目录,简单实用,一看就懂!
  10. 淘宝宝贝图片批量下载教程
  11. Android中禁止WebView滑动
  12. Android九宫格界面实现点击每个格点击跳转界面
  13. android studio天气预报
  14. RHM-M60型挖掘机力矩限制器/载荷指示器
  15. python计算ema_python – 添加一个列(EMA),它是pandas中先前新列值的结果
  16. 小小滑块可笑可笑-安卓滑块验证码通杀方案研究(5)
  17. 卓有成效管理者的八项实践(1)
  18. 互联网晚报 | 10月15日 星期五 | 抖音否认进入外卖行业;孩子王创业板成功上市;领英中国宣布关闭内容发布与互动功能...
  19. java 正方体_Java3D-HelloWorld画正方体
  20. 使用Docker部署Hadoop

热门文章

  1. 2.4G无线麦克风领夹麦一拖二_全双工_杰理JL6976M单芯片方案
  2. $.serializeArray读取不到form中的值
  3. 算法笔记:时间复杂度、空间复杂度 进制转化 秦九韶算法
  4. 朴素贝叶斯分类器:例子解释
  5. 华为鸿蒙最大合作伙伴,全球第三大手机系统「鸿蒙」上线,这19款能抢先用…...
  6. python -m http.server 8000
  7. 超越图灵测试:判断机器是否在思考的现代方法
  8. 机器学习实验之肿瘤分类与预测(SVM)
  9. 计算机课件教程星空,PPT怎么绘制宇宙的另一边思维导图
  10. 听云server探针安装历程