关于通用mapper的使用
关于通用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的使用相关推荐
- Mybatis之通用Mapper使用
增加Maven依赖 <!-- mybatis 通用mapper --> <dependency><groupId>tk.mybatis</groupId> ...
- MyBatis 为什么需要通用 Mapper ?
一.通用 Mapper 的用途 ? 我个人最早用 MyBatis 时,先是完全手写,然后用上了 MyBatis 代码生成器(简称为 MBG),在使用 MBG 过程中,发现一个很麻烦的问题,如果数据库字 ...
- Mybatis 通用 Mapper 使用 ①
简介 官网链接:https://mapperhelper.github.io/docs/ 通用Mapper都可以极大的方便开发人员.可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方 ...
- MyBatis 通用Mapper 入门教程
通用Mapper 简单教程 Mapper 项目地址: [http://git.oschina.net/free/Mapper] 本教程代码地址: [https://github.com/oakshar ...
- 如何使用通用Mapper
集成方法请看上面的文档,集成后,可以继续阅读本页文档. 1. 继承通用的Mapper<T>,必须指定泛型<T> 例如下面的例子: public interface UserIn ...
- Mybatis通用Mapper
极其方便的使用Mybatis单表的增删改查 项目地址:http://git.oschina.net/free/Mapper 优点? 不客气的说,使用这个通用Mapper甚至能改变你对Mybatis单表 ...
- SpringBoot整合Mybatis,使用通用mapper和PageHelper进行分页
乐哉码农 上节介绍了如何整合Security,这节就说下如何再Springboot下使用持久层框架mybatis和牛人封装的通用mapper与mybatis的整合,直接进入正题吧! 1.首先引入我们需 ...
- 通用mapper和分类实现
1 通用Mapper 1.1 通用Mapper介绍 1.1.1 架构设计 说明:使用了通用Mapper后,单表的增删改查操作会自动的进行维护. 问题:如何才能实现数据的通用并且是动态的? 1.2 JP ...
- spring boot整合mybatis+通用mapper+pagehelper分页插件
spring boot整合mybatis+通用mapper+pagehelper分页插件 pom依赖 <?xml version="1.0" encoding="U ...
- 【解析】spring-boot整合通用mapper
问题描述: Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the m ...
最新文章
- Ubuntu11.04 3945ABG无线网卡驱动安装
- VPP /什么是VPP?读这篇文章就够了
- 用DHCP部署WPAD:ISA2006系列之四
- java循环写出多个jlabel_java – 允许多个JLabel中的文本重叠
- 理解神经网络:神经元的概念
- Atitit 学科与知识领域分类门类分类法 目录 1. 学位学科门类是授予学位的学科类别。国际上大体有两种划分方法:	1 2. 三大类法 文理科 医学	1 3. 五大门类	2 4. 13门类	2 5
- git版本管理软件——git储藏
- 本科毕业论文怎么避免查重?
- Word排版如何快速自动生成目录,简单实用,一看就懂!
- 淘宝宝贝图片批量下载教程
- Android中禁止WebView滑动
- Android九宫格界面实现点击每个格点击跳转界面
- android studio天气预报
- RHM-M60型挖掘机力矩限制器/载荷指示器
- python计算ema_python – 添加一个列(EMA),它是pandas中先前新列值的结果
- 小小滑块可笑可笑-安卓滑块验证码通杀方案研究(5)
- 卓有成效管理者的八项实践(1)
- 互联网晚报 | 10月15日 星期五 | 抖音否认进入外卖行业;孩子王创业板成功上市;领英中国宣布关闭内容发布与互动功能...
- java 正方体_Java3D-HelloWorld画正方体
- 使用Docker部署Hadoop
热门文章
- 2.4G无线麦克风领夹麦一拖二_全双工_杰理JL6976M单芯片方案
- $.serializeArray读取不到form中的值
- 算法笔记:时间复杂度、空间复杂度 进制转化 秦九韶算法
- 朴素贝叶斯分类器:例子解释
- 华为鸿蒙最大合作伙伴,全球第三大手机系统「鸿蒙」上线,这19款能抢先用…...
- python -m http.server 8000
- 超越图灵测试:判断机器是否在思考的现代方法
- 机器学习实验之肿瘤分类与预测(SVM)
- 计算机课件教程星空,PPT怎么绘制宇宙的另一边思维导图
- 听云server探针安装历程