MyBatis动态推理参数类型

前言

思考一个问题,前面的#{}和${}的区别中,我们知道了#{},MyBatis底层调用的是preparestatement这种预编译的方式,这种方式sql语句会预先编程 select * from t_user where id = ?这种形式,随后调用setInt(),setString(),…等方法为?赋值,但是myBatis是怎样知道参数是什么类型呢?这个就是MyBatis的动态推理了。具体是怎样推理的我们不再讨论,接下来我们讨论有哪些数据类型,MyBatis可以动态推理出来。

接下来通过各种查询来测试

准备工作
在这里插入图片描述
在这里插入图片描述

简单数据类型且只有一个参数

String

接口中方法

/***
     * 通过姓名来查询
     * @param id
     * @return
     */
    List<Student> selectById(Long id);

Sql映射文件中代码(完整写法,告诉MyBatis我们的参数是什么类型的)

<select id="selectByName" resultType="Student" parameterType="java.lang.String">
        select * from t_student where name = #{name}
    </select>

测试代码

@Test
    public void testSelectByName(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.selectByName("张三");
        for (Student s : students){
            System.out.println(s);
        }
        sqlSession.close();
    }

测试结果
在这里插入图片描述
可以看出可以正常的查出来

缺省一下parameterType

 <select id="selectByName" resultType="Student">
        select * from t_student where name = #{name}
    </select>

再次运行结果
在这里插入图片描述
可以看出MyBatis可以正确地推导出参数类型

java.util.Date

接口中方法

/***
     * 根据birth查询
     * @param birth
     * @return
     */
    List<Student> selectByBirth(Date birth);

sql语句映射文件中代码(缺省版)

<select id="selectByBirth" resultType="Student">
        select * from t_student where birth = #{birth}
    </select>

测试代码

@Test
    public void testSelectByBirth() throws ParseException {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date birth = sdf.parse("1998-02-12");
        List<Student> students = mapper.selectByBirth(birth);
        for (Student s : students){
            System.out.println(s);
        }
        sqlSession.close();
    }

测试结果
在这里插入图片描述
可以看出,Date类型也可以缺省

具体都有哪些简单数据类型可以缺省呢?

经测试以下类型都可以缺省
byte short int long float double char
Byte Short Integer Long Float Double Character
String
java.util.Date
就不一一测试了

Map参数

接口中代码

 /***
     * 根据姓名和年龄来查询
     * @param map
     * @return
     */
    List<Student> selectByNameAndAge(Map<String, Object> map);

Sql映射文件中代码(缺省版本)

<select id="selectByNameAndAge" resultType="Student">
        select * from t_student where name = #{sname} and age = #{sage}
    </select>

注意#{}中的值必须是map中的键值
测试代码

@Test
    public void testSelectByNameAndAge(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("sname","张三");
        map.put("sage",20);
        List<Student> students = mapper.selectByNameAndAge(map);
        for(Student s : students)
            System.out.println(s);
        sqlSession.close();
    }

运行结果
在这里插入图片描述
得出结论Map也可以缺省

实体类参数

接口中代码

/***
     * 保存学生信息
     * @param s
     * @return
     */
    int insert(Student s);

Sql映射文件中代码(缺省parameterType)

<insert id="insert">
        insert into t_student values(null,#{name},#{age},#{height},#{birth},#{sex})
    </insert>

测试代码

@Test
    public void testInsert(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = new Student(null, "赵六", 18, 1.7, new Date(), '男');
        int count = mapper.insert(student);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

运行结果
在这里插入图片描述
在这里插入图片描述
可以看出参数是实体类的时候也是可以缺省的

多个参数的情况

接口中代码

/***
     * 通过姓名和性别来进行查询
     * @param name
     * @param sex
     * @return
     */
    List<Student> selectByNameAndSex(String name,Character sex);

Sql映射文件中代码(缺省参数类型)

 <select id="selectByNameAndSex" resultType="Student">
        select * from t_student where name = #{name} and sex = #{sex}
    </select>

测试代码

@Test
    public void testSelectByNameAndSex(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.selectByNameAndSex("张三", '男');
        for(Student s : students)
            System.out.println(s);
        sqlSession.close();
    }

测试结果
在这里插入图片描述

可以看出运行出现了问题,提醒参数name没有找到,并且提醒可用的参数为[arg1, arg0, param1, param2]
更改Sql映射文件中的代码为如下

<select id="selectByNameAndSex" resultType="Student">
        select * from t_student where name = #{arg0} and sex = #{arg1}
    </select>

再次运行结果为
在这里插入图片描述
将文件更改为

<select id="selectByNameAndSex" resultType="Student">
        select * from t_student where name = #{param1} and sex = #{param2}
    </select>

也可以通过

结论

可以看出当参数有多个的时候,MyBatis已经为我们起好了参数名,我们需要正确地使用MyBatis为我们准备好的参数名

arg0 是第⼀个参数

param1是第⼀个参数

arg1 是第⼆个参数

param2是第⼆个参数

实现原理:实际上在mybatis底层会创建⼀个map集合,以arg0/param1为key,以⽅法上的参数为 value
例如如下代码

Map<String,Object> map = new HashMap<>();
map.put("arg0", name);
map.put("arg1", sex);
map.put("param1", name);
map.put("param2", sex);
// 所以可以这样取值:#{arg0} #{arg1} #{param1} #{param2}
// 其本质就是#{map集合的key}

注意:使⽤mybatis3.4.2之前的版本时:要⽤#{0}和#{1}这种形式。

疑问:我们必须使用MyBatis为我们准备的参数吗? @Param注解登场


@Param注解(命名参数)

如果我们不想使用系统提供的参数名,我们可以自己规定吗?答案是肯定的

我们可以使用@Param来为参数起名字(也就是底层Map中参数对应的key值名)

实战

接口中的代码

/***
     * 通过姓名和性别来进行查询
     * @param name
     * @param sex
     * @return
     */
    List<Student> selectByNameAndSex(@Param(value = "name") String name,@Param("sex") Character sex);

value = 可以省略

更改Sql映射文件中的代码

<select id="selectByNameAndSex" resultType="Student">
        select * from t_student where name = #{name} and sex = #{sex}
    </select>

再次运行刚才的测试代码
运行结果
在这里插入图片描述
可以看出我们的@Param起作用了

核心:@Param(“这⾥填写的其实就是map集合的key”)
希望通过这篇文章大家都可以对MyBatis中的参数有一个更加深的理解

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot MyBatis中的动态参数是指在数据库查询中根据不同的条件动态生成SQL语句的参数。在实际开发中,我们经常需要根据不同的条件查询数据库中的数据,例如根据用户输入的关键字、日期范围等进行查询。 Spring Boot MyBatis提供了丰富的动态参数处理机制,方便我们根据不同的条件生成动态SQL语句。其中最常用的方式是使用MyBatis框架提供的动态SQL标签,包括if、choose、when、otherwise等标签。 使用动态SQL标签,我们可以根据条件判断动态生成SQL语句的一部分。例如,在查询用户信息时,如果用户输入了关键字,我们可以根据关键字在SQL中拼接WHERE语句;如果用户没有输入关键字,则不需要拼接WHERE语句。 另外,Spring Boot MyBatis还提供了注解方式的动态参数处理方式。我们可以使用注解@Param指定方法参数的名称,在SQL语句中引用该名称的参数。通过在SQL语句中使用#{}占位符,并在方法中传递对应的参数值,实现动态SQL语句的生成。 动态参数的使用可以大大提高我们的开发效率和代码复用性。我们可以根据具体的业务需求灵活构建动态SQL语句,无需为每个查询场景编写单独的SQL语句。同时,动态参数也可以防止SQL注入攻击,提高系统的安全性。 总之,Spring Boot MyBatis提供了方便灵活的动态参数处理机制,可以根据不同的条件生成动态SQL语句,提高开发效率,保证系统的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只呆小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值