Spring Boot MyBatis升级篇-注解-动态SQL(if test)-方案二:@Provider(8)
1)动态语言注解
(2)@Provider使用思路
(3)@SelectProvider小试牛刀
(4)@SelectProvider初露锋芒
(5)@SelectProvider过关斩将
(6)@InsertProvider小弟不敢当
(7)@UpdateProvider你加我来改
(8)@DeleteProvider不高兴就删
接下来看下具体的内容:
(1)动态语言注解
对于创建动态的查的语言。MyBatis提供了多个注解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,这些都是建立动态语言和让MyBatis执行这些语言。
(2)@Provider使用思路
对于MyBatis提供的几个@Provider,里面最主要的参数是type,也就是sql类的Calss对象,另外就是对应的方法名,我们看SelectProvider的源代码:
Java代码 收藏代码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SelectProvider {
Class<?> type(); String method();
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SelectProvider {
Class<?> type(); String method();
}
所以要实现动态的SQL查询,那么大体的思路就是,编写一个SqlProvider,比如:DemoSqlProvider,在此方法中返回一条SQL语句即可。然后在Mapper类中使用@SelectProvider注解,指定provider类和对应的SQL方法。
接下来我们来解决上一篇博客的问题:
问题:有一个表中有id,name,email等字段,有这么一个查询要求:我们希望的是如果name不为null的话,那么就当做条件,否则就不要当做条件;如果email不为null,那么就当做条件,否则不当做条件。
接下里看看怎么使用@SelectProvider破。
(3)@SelectProvider小试牛刀
我们先编写一个DemoSqlProvider,代码如下:
package com.kfit.demo.mapper;
import com.kfit.demo.bean.Demo;
public class DemoSqlProvider {
/**
* 查询语句.
* @param demo
* @return
*/
public String select5(Demo demo){
StringBuffer sql = new StringBuffer("select *from demo where 1=1 ");
if(demo.getName() != null){
sql.append(" and name=#{name}");
}
if(demo.getEmail() != null){
sql.append(" and email=#{email}");
}
return sql.toString();
}
}
package com.kfit.demo.mapper;
import com.kfit.demo.bean.Demo;
public class DemoSqlProvider {
/**
* 查询语句.
* @param demo
* @return
*/
public String select5(Demo demo){
StringBuffer sql = new StringBuffer("select *from demo where 1=1 ");
if(demo.getName() != null){
sql.append(" and name=#{name}");
}
if(demo.getEmail() != null){
sql.append(" and email=#{email}");
}
return sql.toString();
}
}
在DemoMapper中加入查询方法:
@SelectProvider(type=DemoSqlProvider.class,method="select5")
public List<Demo> select5(Demo demo);
@SelectProvider(type=DemoSqlProvider.class,method="select5")
public List<Demo> select5(Demo demo);
这里使用@SelectProvider,不是@Select了。
访问1:http://127.0.0.1:8080/select4会返回全部数据,动态SQL是:
SELECT * from Demo WHERE 1=1
- SELECT * from Demo WHERE 1=1
访问2:http://127.0.0.1:8080/select4?name=王五会返回name=王五的数据,动态SQL是:
- SELECT * from Demo WHERE 1=1 and name=?
- SELECT * from Demo WHERE 1=1 and name=?
访问3:http://127.0.0.1:8080/select4?name=王五&email=aa@qq.com会返回name=王五并且email=aa@qq.com的数据,动态SQL是:
- SELECT * from Demo WHERE 1=1 and name=? and email=?
- SELECT * from Demo WHERE 1=1 and name=? and email=?
(4)@SelectProvider初露锋芒
上面的代码直接纯SQL编写了,可读性还是相对差了点,MyBatis提供了SQL类(org.apache.ibatis.jdbc.SQL),可以让代码看起来更有意义。
在DemoSqlProvider中加入方法:
/**
* 查询语句.使用SQL
* @param demo
* @return
*/
public String select6(final Demo demo){
return new SQL(){{
SELECT("id,name,email");
FROM("demo");
if(demo.getName() != null){
WHERE("name=#{name}");
}
if(demo.getEmail() != null){
WHERE("email=#{email}");
}
}}.toString();
}
在DempMapper中加入代码:
@SelectProvider(type=DemoSqlProvider.class,method="select6")
public List<Demo> select6(Demo demo);
(5)@SelectProvider过关斩将
原以为万事大吉了,开心的不行,于是乎,信手拈来句代码,在查询代码加入:
PageHelper.startPage(1, 2);整个代码如下:
@RequestMapping("/select6")
public List<Demo> select6(Demo demo){
PageHelper.startPage(, );
return demoService.select6(demo);
}
@RequestMapping("/select6")
public List<Demo> select6(Demo demo){
PageHelper.startPage(, );
return demoService.select6(demo);
}
运行,访问:http://127.0.0.1:8080/select6完了,这是什么鬼:
nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'providerTakesParameterObject' in 'class org.apache.ibatis.builder.annotation.ProviderSqlSource'
出现以上问题,是由于我们使用的PageHelper版本导致的,升级版本即可。
运行,访问:http://127.0.0.1:8080/select6完了,这是什么鬼:
nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'providerTakesParameterObject' in 'class org.apache.ibatis.builder.annotation.ProviderSqlSource'
出现以上问题,是由于我们使用的PageHelper版本导致的,升级版本即可。
原先的版本为:
Xml代码 收藏代码
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.</version>
</dependency>
[xml] view plain copy
升级为:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.2.1</version>
</dependency>
貌似:4.1.5就支持@SelectProvider分页查询了(未进行验证)。
(6)@InsertProvider小弟不敢当
最麻烦的查询搞定了之后,这个就简单了,
在DemoSqlProvider中加入如下代码:
/**
* 查询语句.使用SQL
* @param demo
* @return
*/
public String save3(final Demo demo){
return new SQL(){{
INSERT_INTO("demo");
//多个写法.
INTO_COLUMNS("name","email");
INTO_VALUES("#{name}","#{email}"); //条件写法.
// if(demo.getName() != null){
// VALUES("name","#{name}");
// }
// if(demo.getEmail() != null){
// VALUES("email","#{email}");
// } }}.toString();
}
在DemoMapper中加入如下代码:
ava代码 收藏代码
@InsertProvider(type=DemoSqlProvider.class,method="save3")
@Options(keyProperty="id",keyColumn="id",useGeneratedKeys=true)
public void save3(Demo demo);
(7)@UpdateProvider你加我来改
DemoSqlProvider中的代码如下:
Java代码 收藏代码
/**
* @param demo
* @return
*/
public String update2(final Demo demo){
return new SQL(){{
UPDATE("demo"); //条件写法.
if(demo.getName() != null){
SET("name=#{name}");
}
if(demo.getEmail() != null){
SET("email=#{email}");
}
WHERE("id=#{id}");
}}.toString();
}
在DemoMapper中的代码:
码 收藏代码
@UpdateProvider(type=DemoSqlProvider.class,method="update2")
public int update2(Demo demo);
(8)@DeleteProvider不高兴就删
DemoSqlProvider代码:
Java代码 收藏代码
/**
* @param demo
* @return
*/
public String delete2(){
return new SQL(){{
DELETE_FROM("demo");
WHERE("id=#{id}");
}}.toString();
}
在DemoMapper中的代码:
@UpdateProvider(type=DemoSqlProvider.class,method="delete2")
public int delete2(int id);
Spring Boot MyBatis升级篇-注解-动态SQL(if test)-方案二:@Provider(8)的更多相关文章
- 54. spring boot日志升级篇—logback【从零开始学Spring Boot】
在<44. Spring Boot日志记录SLF4J>章节中有关相关的介绍,这里我们在深入的了解下logback框架. 为什么要使用logback ? --在开发中不建议使用System. ...
- 52. spring boot日志升级篇—log4j多环境不同日志级别的控制【从零开始学Spring Boot】
在上一章节中我们介绍了,仅通过log4j-spring.properties对日志级别进行控制,对于需要多环境部署的环境不是很方便,可能我们在开发环境大部分模块需要采用DEBUG级别,在测试环境可能需 ...
- 50. Spring Boot日志升级篇—log4j【从零开始学Spring Boot】
如果你使用的是spring boot 1.4.0版本的话,那么你可能需要配合以下文章进行学习 90.Spring Boot 1.4 使用log4j错误[从零开始学Spring Boot] Log4j是 ...
- Spring boot Mybatis 整合(注解版)
之前写过一篇关于springboot 与 mybatis整合的博文,使用了一段时间spring-data-jpa,发现那种方式真的是太爽了,mybatis的xml的映射配置总觉得有点麻烦.接口定义和映 ...
- 持久层之 MyBatis: 第二篇 :动态SQL And多表查询
MyBatis入门到精通 完整CRUD UserDaoImpl 编写UserDao对应的UserDaoMapper.xml 添加UserDao的测试用例 编写UserDao的测试用例 解决数据库字段名 ...
- 49. spring boot日志升级篇—理论【从零开始学Spring Boot】
我们之前在其中的一篇文章介绍过如何在spring boot中使用日志记录SLF4J. Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如 ...
- 57. Spring 自定义properties升级篇【从零开始学Spring Boot】
之前在两篇文章中都有简单介绍或者提到过 自定义属性的用法: 25.Spring Boot使用自定义的properties[从零开始学Spring Boot] 51. spring boot属性文件之多 ...
- (45). Spring Boot MyBatis连接Mysql数据库【从零开始学Spring Boot】
大家在开发的时候,会喜欢jdbcTemplate操作数据库,有喜欢JPA操作数据库的,有喜欢MyBatis操作数据库的,对于这些我个人觉得哪个使用顺手就使用哪个就好了,并没有一定要使用哪个,个人在实际 ...
- Spring boot Mybatis 整合(完整版)
个人开源项目 springboot+mybatis+thymeleaf+docker构建的个人站点开源项目(集成了个人主页.个人作品.个人博客) 朋友自制的springboot接口文档组件swagge ...
随机推荐
- cocos2d-x系列笔记技巧篇(2)---关于CREATE_FUNC宏的用法
FROM://http://blog.csdn.net/jinciyulang/article/details/8631889 阅读cocos2d-x demo的代码,我们会看到有些头文件中使用CRE ...
- python测试开发django-33.admin后台一对一关系OneToOneField
前言 假如有一张表(Card)记录用户的卡号信息和用户名,现在需要新增一个小功能,记录用户的手机号,邮箱和住址等更多信息. 为了不影响原来的表设计,可以新增一张表(CardDetail),专门记录用户 ...
- Oracle简易界面工具 (Oracle 10g, Oracle 11g)
Oracle简易界面工具 背景:偶在远程机上干活,须要调用到 Oracle 11gserver的数据,远程机上已安装Oracle client, 但 sql plus 和 sql developer ...
- Kubernetes中StatefulSet介绍
StatefulSet 是Kubernetes1.9版本中稳定的特性,本文使用的环境为 Kubernetes 1.11.如何搭建环境可以参考kubeadm安装kubernetes V1.11.1 集群 ...
- .condarc(conda 配置文件)、换国内源
原文地址 https://blog.csdn.net/lanchunhui/article/details/71379555 Configuration — Conda documentation . ...
- SQL Server中取汉字拼音的函数
)) ) ) ) ) ), py end return @pinyin END GOSELECT dbo.fn_GetP ...
- EF6源码学习-准备篇
现在对于.net开发人员来说EF已经很流行了,虽然我在2010年的时候就用过EF,也看过几本书,但是还没有仔细研究EF的code, 曾经也尝试阅读EF5的源代码,后来由于时间关系也没有坚持住.现在计划 ...
- ORM数据库框架 SQLite ORMLite MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- python3 文件及文件夹路径相关
1. #返回当前文件所在的目录 currentDir = path.dirname(__file__) # __file__ 为当前文件 2.获得某个路径的父级目录: parent_path = os ...
- Ubuntu升级到18.04
1.更新 sudo apt-get update 2.升级 sudo apt-get upgrade 3.检测最新版本 sudo update-manager -c -d 然后就会弹出窗口,提示ubu ...