Mybatis动态sql中@Param使用详解

 更新时间:2023年10月08日 08:32:25   作者:riun、  
这篇文章主要介绍了Mybatis动态sql中@Param使用详解,当方法的参数为非自定义pojo类型,且使用了动态sql,那么就需要在参数前加上@Param注解,需要的朋友可以参考下

Mybatis中的@param注解的使用场景

1、方法有多个参数

2、方法参数要取别名

3、XML 中的 SQL 使用了 $

4、动态sql中参数是非自定义pojo类型

前三种,相信大家都非常熟练,这里不再多说,这里主要说下第四种。

方法的参数为非自定义pojo类型,且使用了动态sql,那么就需要在参数前加上@Param注解。

测试:(此处使用SpringBoot2.0+ 、Mybatis-Plus)

数据库数据

在这里插入图片描述

代码

pojo:

/**
 * @author: HanXu
 * on 2019/12/18
 * Class description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Test {
    private Integer id;
    private String name;
    private Integer age;
    private Integer num;
}

mapper接口:

/**
 * @author: HanXu
 * on 2019/12/18
 * Class description:
 */
public interface TestMapper extends BaseMapper<Test> {
    Test sel(Test t);
    Test seli(Integer id);
    Test seli2(@Param("id")Integer id);
    Test sels(String s);
    Test sels2(@Param("s")String s);
}

对应的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="hx.insist.demo.mapper.TestMapper">
    <select id="sel" parameterType="hx.insist.demo.domain.Test" resultType="hx.insist.demo.domain.Test">
        select * from test
        where 1 = 1
        <if test="id!=null">
            and id = #{id}
        </if>
        <if test="name!=null">
            and name = #{name}
        </if>
        <if test="age!=null">
            and age = #{age}
        </if>
        <if test="num!=null">
            and num = #{num}
        </if>
    </select>
    <select id="seli" parameterType="Integer" resultType="hx.insist.demo.domain.Test">
        select * from test
        where 1 = 1
        <if test="id!=null">
            and id = #{id}
        </if>
    </select>
    <select id="seli2" parameterType="Integer" resultType="hx.insist.demo.domain.Test">
        select * from test
        where 1 = 1
        <if test="id!=null">
            and id = #{id}
        </if>
    </select>
    <select id="sels" resultType="hx.insist.demo.domain.Test">
        select * from test
        where 1 = 1
        <if test="s!=null">
            and name = #{s}
        </if>
    </select>
    <select id="sels2" resultType="hx.insist.demo.domain.Test">
        select * from test
        where 1 = 1
        <if test="s!=null">
            and name = #{s}
        </if>
    </select>
</mapper>

service层:

/**
 * @author: HanXu
 * on 2019/12/18
 * Class description:
 */
@Service
public class TestService {
    @Resource
    private TestMapper testMapper;
    //测试自定义的存在setter方法的对象
    public void selTest(){
         Test t = new Test();
        t.setId(1);
        Test sel = testMapper.sel(t);
        System.out.println(sel);
    }
    //测试Integer
    public void seliTest(){
        Test seli = testMapper.seli(1);
        System.out.println(seli);
    }
    //测试String
    public void selsTst(){
        Test aaa = testMapper.sels("aaa");
        System.out.println(aaa);
    }
    //测试Integer,且写了@Param
    public void seliTest2(){
        Test seli = testMapper.seli2(1);
        System.out.println(seli);
    }
    //测试String,且写了@Param
    public void selsTest2(){
        Test test = testMapper.sels2("aaa");
        System.out.println(test);
    }
}

controller层:

@GetMapping("testT")
    public ResponseEntity test(){
        testService.selTest();
        return ResponseEntity.ok().build();
    }
    @GetMapping("testI")
    public ResponseEntity testi(){
        testService.seliTest();
        return ResponseEntity.ok().build();
    }
    @GetMapping("testS")
    public ResponseEntity tests(){
        testService.selsTst();
        return ResponseEntity.ok().build();
    }
    @GetMapping("testI2")
    public ResponseEntity testI2(){
        testService.seliTest2();
        return ResponseEntity.ok().build();
    }
    @GetMapping("testS2")
    public ResponseEntity testS2(){
        testService.selsTest2();
        return ResponseEntity.ok().build();
    }

测试结果

测试Test seli(Integer id);

在这里插入图片描述

在这里插入图片描述

测试Test seli2(@Param(“id”)Integer id);

在这里插入图片描述

在这里插入图片描述

测试Test sels(String s);

在这里插入图片描述

在这里插入图片描述

测试Test sels2(@Param(“s”)String s);

在这里插入图片描述

在这里插入图片描述

测试Test sel(Test t);

在这里插入图片描述

在这里插入图片描述

结论

上述5个测试用例中 分为三对:

    Test sel(Test t);//5
    Test seli(Integer id);//1
    Test seli2(@Param("id")Integer id);//2
    Test sels(String s);//3
    Test sels2(@Param("s")String s);//4

1和2是一对测试,除了2比1多了一个@Param注解之外其他全部相同,测试结果表示:加了注解的能正确执行,未加注解的不能正确执行。

3和4是一对测试,除了4比3多了一个@Param注解之外其他全部相同,测试结果表示:加了注解的能正确执行,未加注解的不能正确执行。

5和1、3是一对测试,不同之处在于5中的参数是自定义pojo,里面每个属性都有setter、getter方法,结果表示:在不加@Param注解的情况下,自定义pojo作为参数可以正常执行,非自定义pojo(没有参数的getter方法)作为参数不能正常执行。

以上基于sql语句中使用了动态sql(存在不确定的语句)

我的猜想:

这跟Mybatis内部实现有关。当你使用动态sql时,#{}去拿你的参数时,默认将参数当成了pojo类型,去取对应属性的getter方法,而这时如果你的参数不是pojo类型,是一个java定义好的类型,比如参数为Integer id,String s,使用#{}得到它的值时,Mybatis就会去直接取相应的getter方法,比如反射Integer类,取getId()方法 、反射String类,取getS()方法,但是这些类中并没有相应的方法,那么就会报错:

org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘id’ in ‘class java.lang.Integer’
org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘s’ in ‘class java.lang.String’

到此这篇关于Mybatis动态sql中@Param使用详解的文章就介绍到这了,更多相关Mybatis动态sql内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot 与 Kotlin 上传文件的示例代码

    Spring Boot 与 Kotlin 上传文件的示例代码

    这篇文章主要介绍了Spring Boot 与 Kotlin 上传文件的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • 详解Java从工厂方法模式到 IOC/DI思想

    详解Java从工厂方法模式到 IOC/DI思想

    工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口。本文将详细介绍Java从工厂方法模式到 IOC/DI思想。
    2021-06-06
  • spring boot使用WebClient调用HTTP服务代码示例

    spring boot使用WebClient调用HTTP服务代码示例

    这篇文章主要介绍了spring boot使用WebClient调用HTTP服务代码示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java编码辅助工具Mapstruct用法详解

    Java编码辅助工具Mapstruct用法详解

    这篇文章主要介绍了Java编码辅助工具Mapstruct用法详解,手动编码setter/getter各个对应属性,会显得臃肿繁琐。通过Mapstruct框架可简单方便地完成这一工作。,需要的朋友可以参考下
    2019-06-06
  • java的NIO管道用法代码分享

    java的NIO管道用法代码分享

    这篇文章主要介绍了java的NIO管道用法代码分享,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 动态代理模拟实现aop的示例

    动态代理模拟实现aop的示例

    下面小编就为大家带来一篇动态代理模拟实现aop的示例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望对大家有所帮助
    2017-11-11
  • Java编程几个循环实例代码分享

    Java编程几个循环实例代码分享

    这篇文章主要介绍了Java编程几个循环实例代码分享,多看多练,小编觉得还是挺不错的,这里分享给大家,供需要的朋友参考。
    2017-10-10
  • java虚拟机中多线程总结

    java虚拟机中多线程总结

    在本篇内容中小编给大家分享的是关于java虚拟机中多线程的知识点总结内容,需要的朋友们参考学习下。
    2019-06-06
  • Java实现基于JDBC操作mysql数据库的方法

    Java实现基于JDBC操作mysql数据库的方法

    这篇文章主要介绍了Java实现基于JDBC操作mysql数据库的方法,结合实例形式分析了java使用JDBC实现针对mysql数据库的连接、查询、输出等相关操作技巧,需要的朋友可以参考下
    2017-12-12
  • SpringBoot中整合Minio文件存储的安装部署过程

    SpringBoot中整合Minio文件存储的安装部署过程

    这篇文章主要介绍了SpringBoot整合Minio文件存储的相关知识,详细介绍了Minio安装部署过程,需要的朋友可以参考下
    2022-04-04

最新评论