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

  1. SELECT * from Demo WHERE 1=1

访问2:http://127.0.0.1:8080/select4?name=王五会返回name=王五的数据,动态SQL是:

  1. SELECT * from Demo WHERE 1=1 and name=?
  2. 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是:

  1. SELECT * from Demo WHERE 1=1 and name=? and email=?
  2. 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)的更多相关文章

  1. 54. spring boot日志升级篇—logback【从零开始学Spring Boot】

    在<44. Spring Boot日志记录SLF4J>章节中有关相关的介绍,这里我们在深入的了解下logback框架. 为什么要使用logback ? --在开发中不建议使用System. ...

  2. 52. spring boot日志升级篇—log4j多环境不同日志级别的控制【从零开始学Spring Boot】

    在上一章节中我们介绍了,仅通过log4j-spring.properties对日志级别进行控制,对于需要多环境部署的环境不是很方便,可能我们在开发环境大部分模块需要采用DEBUG级别,在测试环境可能需 ...

  3. 50. Spring Boot日志升级篇—log4j【从零开始学Spring Boot】

    如果你使用的是spring boot 1.4.0版本的话,那么你可能需要配合以下文章进行学习 90.Spring Boot 1.4 使用log4j错误[从零开始学Spring Boot] Log4j是 ...

  4. Spring boot Mybatis 整合(注解版)

    之前写过一篇关于springboot 与 mybatis整合的博文,使用了一段时间spring-data-jpa,发现那种方式真的是太爽了,mybatis的xml的映射配置总觉得有点麻烦.接口定义和映 ...

  5. 持久层之 MyBatis: 第二篇 :动态SQL And多表查询

    MyBatis入门到精通 完整CRUD UserDaoImpl 编写UserDao对应的UserDaoMapper.xml 添加UserDao的测试用例 编写UserDao的测试用例 解决数据库字段名 ...

  6. 49. spring boot日志升级篇—理论【从零开始学Spring Boot】

    我们之前在其中的一篇文章介绍过如何在spring boot中使用日志记录SLF4J. Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如 ...

  7. 57. Spring 自定义properties升级篇【从零开始学Spring Boot】

    之前在两篇文章中都有简单介绍或者提到过 自定义属性的用法: 25.Spring Boot使用自定义的properties[从零开始学Spring Boot] 51. spring boot属性文件之多 ...

  8. (45). Spring Boot MyBatis连接Mysql数据库【从零开始学Spring Boot】

    大家在开发的时候,会喜欢jdbcTemplate操作数据库,有喜欢JPA操作数据库的,有喜欢MyBatis操作数据库的,对于这些我个人觉得哪个使用顺手就使用哪个就好了,并没有一定要使用哪个,个人在实际 ...

  9. Spring boot Mybatis 整合(完整版)

    个人开源项目 springboot+mybatis+thymeleaf+docker构建的个人站点开源项目(集成了个人主页.个人作品.个人博客) 朋友自制的springboot接口文档组件swagge ...

随机推荐

  1. C++笔记:头文件的作用和写法

    from://http://ceeji.net/blog/c%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%A4%B4%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD% ...

  2. WordPress主题开发实例:查询单篇文章

    xxx/?page_id=5 想在首页调用以上页面的内容怎么做呢? 完整: <?php //查询 $my_query = new WP_Query( 'page_id=5' ); if($my_ ...

  3. WordPress主题开发:设置和获取浏览次数

    将以下代码放在functions.php,一个是获取阅读量,一个是设置阅读量 <?php /** * getPostViews()函数 * 功能:获取阅读数量 * 在需要显示浏览次数的位置,调用 ...

  4. OAuth:Access to shared resources via web applications

    A web application which wants to gain access to shared resources should redirect the user to a page ...

  5. Unite 2017 | 从《闹闹天宫》看MOBA游戏里的网络同步技术

    http://mp.weixin.qq.com/s/0v0EU79Q6rFafrh8ptlmhw 在Unite 2017 Shanghai案例分享专场,来自蓝港互动<闹闹天宫>项目组的主程 ...

  6. 女超人第三季/全集Supergirl迅雷下载

    看上去<超女>男星大卫·海伍德对第二季中机械超人的造型不太满意,这位扮演过火星猎人的男演员在澳大利亚的超新星漫展上透露过,他并不是很期待他在DC电视剧中扮演的第二个角色(机械超人). “我 ...

  7. ios之gcd浅析

    A.普通的GCD异步运行与主线程更新写法: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^ ...

  8. 深入理解ClassLoader工作机制(jdk1.8)

    ClassLoader 顾名思义就是类加载器,ClassLoader 作用: 负责将 Class 加载到 JVM 中    审查每个类由谁加载(父优先的等级加载机制)    将 Class 字节码重新 ...

  9. ack-grep 代码全文搜索

    安装 ubuntu下要安装ack-grep,因为在debian系中,ack这个名字被其他的软件占用了. sudo apt-get install ack-grep 特点 大家都说自己的东西好,因此ac ...

  10. winform中的TreeView的数据绑定

    #region 绑定TreeView /// <summary> /// 绑定TreeView(利用TreeNode) /// </summary> /// <param ...