Mybatis动态sql中@Param使用详解
作者:riun、
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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!