MyBatis 参数上的处理的细节内容

1. MyBatis 参数上的处理的细节内容

文章目录

  • 1. MyBatis 参数上的处理的细节内容
  • 2. MyBatis 参数上的处理
  • 3. 准备工作
  • 4. 单个(一个)参数
    • 4.1 单个(一个)简单类型作为参数
    • 4.2 单个(一个) Map集合 作为参数
    • 4.3 单个(一个) 实体类POJO作为参数
  • 5. 多个参数
    • 5.1 @Param注解(命名参数)
  • 6. @Param 注解源码分析
  • 7. 总结:
  • 8. 最后:


2. MyBatis 参数上的处理

3. 准备工作

数据表结构的设计,数据表名为:t_student

在这里插入图片描述

t_student 表中的数据信息:

在这里插入图片描述

pom.xml 文件当中配置相关的依赖的 jar 包如下:

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.rainbowsea</groupId><artifactId>mybatis-005-crud-blog</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><!--        mybatis 的依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><!--        mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!--        引入 logback的依赖,这个日志框架实现了slf4j 规范--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency></dependencies></project>

配置 logback 的配置文件,用于打印显示,我们的日志信息,方便我们查看我们的运行过程,效果。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"><!-- 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!--mybatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR --><root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>

配置 MyBatis 的核心配置文件,

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--    起别名--><typeAliases><!--  使用 <package>	还可以将这个包下的所有的类的全部自动起别名,别名就是简名,不区分大小写 --><package name="com.rainbowsea.mybatis.pojo"/></typeAliases><environments default="mybatis"><environment id="mybatis"><!--            MANAGED 没有用第三框架管理的话,都是会被提交的,没有事务上的管理了 --><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="MySQL123"/></dataSource></environment></environments><mappers><!-- 这里也是可以使用 package 包名扫描,但是同样的:对应接口路径要一致,接口名一致--><package name="com.rainbowsea.mybatis.mapper"></package></mappers>
</configuration>

对照 tstudent 创建的ORM 映射的 Car 类

注意:在MyBatis 当中对应的ORM ,一般在框架里对应的 Bean实体类,一定要实现该 set 和 get 方法以及无参数构造方法,无法框架无法使用反射机制,进行操作

建议用包装类,这样可以防止 Null的问题,因为(简单类型 int num = null ,是不可以赋值为 null)的编译无法通过

在这里插入图片描述

package com.rainbowsea.mybatis.pojo;import java.util.Date;public class Student {private Long id;private String name;private Integer age;private Double height;private Date birth;private Character sex;public Student() {}public Student(Long id, String name, Integer age, Double height, Date birth, Character sex) {this.id = id;this.name = name;this.age = age;this.height = height;this.birth = birth;this.sex = sex;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", height=" + height +", birth=" + birth +", sex=" + sex +'}';}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Double getHeight() {return height;}public void setHeight(Double height) {this.height = height;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}public Character getSex() {return sex;}public void setSex(Character sex) {this.sex = sex;}
}

在这里插入图片描述

4. 单个(一个)参数

4.1 单个(一个)简单类型作为参数

简单类型包括:

  • byte short int long float double char
  • Byte Short Integer Long Float Double Character
  • String
  • java.util.Date
  • java.sql.Date

需求:根据name查、根据id查、根据birth查、根据sex查。

第一个:根据 id 查记录

在这里插入图片描述

package com.rainbowsea.mybatis.mapper;import com.rainbowsea.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;public interface StudentMapper {
// 单个参数上的处理/*** 当接口中的方法的参数只有一个(单个参数),并且参数的数据类型都是简单类型* 根据id查询,name查询,birth查询,sex查询*/List<Student> selectById(Long id);}

编写向对应上的:SQL 映射文件的内容:

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.StudentMapper"><!--	id 要是 namespace 对应接口上的方法名: --><!--    parameterType 属性的作用:告诉mybatis框架,我这个方法的参数类型是什么类型的mybatis 框架自身带有类型自动推断的机制,所以大部分情况下 parameterType 属性都是可以省略不写的。select * from t_student where id = ?ps.setLong(1,1L)ps.setString(1,"张三")ps.setDate(1,new Date())ps.setInt(1,100)...mybatis 底层到底调用setXxx的哪个方法,取决于parameterType属性的值注意: mybatis框架时间上内置了很多别名,可以参考开发手册--><select id="selectById" resultType="Student" parameterType="java.lang.Long">select id, name, age, height, birth, sexfrom t_studentwhere id = #{id}</select>
</mapper>

paramterType 属性的作用:

告诉mybatis框架,我这个方法的参数类型是什么类型的
mybatis 框架自身带有类型自动推断的机制,所以大部分情况下 parameterType 属性都是可以省略不写的。
select * from t_student where id = ?
ps.setLong(1,1L)
ps.setString(1,“张三”)
ps.setDate(1,new Date())
ps.setInt(1,100)

mybatis 底层到底调用setXxx的哪个方法,取决于parameterType属性的值
注意: mybatis框架时间上内置了很多别名,可以参考开发手册

resultType 属性的作用:

指定 select 查询,返回的结果集,封装到哪里,哪个对象当中,这里由于前面我们做好了关于别名上的准备工作,所以这里我们可以直接有用别名(简名)

Java程序编程,运行测试:

在这里插入图片描述

package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.StudentMapper;
import com.rainbowsea.mybatis.pojo.Student;
import com.rainbowsea.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class TestStudentMapper {@Testpublic void testSelectById() {SqlSession sqlSession = SqlSessionUtil.openSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);List<Student> students = mapper.selectById(2L);students.forEach(student -> {System.out.println(student);});sqlSession.close();}
}

在MyBatis 框架当中 内置了很多的别名,可以参考开发手册https://mybatis.net.cn/configuration.html#typeHandlers。

在这里插入图片描述


其实对于Mybatis 框架来说,简单类型对于mybatis来说都是可以自动类型识别的:

在MyBatis 框架当中如下,为的类型被定义为简单类型

简单类型包括:

  • byte short int long float double char

  • Byte Short Integer Long Float Double Character

  • String

  • java.util.Date

  • java.sql.Date

  • 也就是说对于mybatis来说,它是可以自动推断出ps.setXxxx()方法的。ps.setString()还是ps.setInt()。它可以自动推断。

如下,我们不指定所传的参数类型,依靠MyBatis 的自行推断的机制,自行推断。

根据birth查、根据sex查。

在这里插入图片描述

package com.rainbowsea.mybatis.mapper;import com.rainbowsea.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;public interface StudentMapper {
// 单个参数上的处理/*** 当接口中的方法的参数只有一个(单个参数),并且参数的数据类型都是简单类型* 根据id查询,name查询,birth查询,sex查询*/List<Student> selectByBirth(Date birth);List<Student> selectBySex(Character sex);}

对应的SQL语句映射文件的编写

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.StudentMapper"><select id="selectByBirth" resultType="Student">select id, name, age, height, birth, sexfrom t_studentwhere birth = #{birth}</select><select id="selectBySex" resultType="Student">select id, name, age, height, birth, sexfrom t_studentwhere sex = #{sex}</select></mapper>

Java程序测试,编写

根据 brith 查询

在这里插入图片描述

    //java.util.Date; java.sql.Date 他们在mybatis当中都是为简单类型@Testpublic void testSelectByBrith() throws ParseException {SqlSession sqlSession = SqlSessionUtil.openSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");Date birth = simpleDateFormat.parse("2020-06-06");List<Student> students = mapper.selectByBirth(birth);students.forEach(student -> {System.out.println(student);});sqlSession.close();}

根据 sex 查询

在这里插入图片描述

public class TestStudentMapper {@Testpublic void testSelectBySex() {SqlSession sqlSession = SqlSessionUtil.openSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);List<Student> students = mapper.selectBySex('男');students.forEach(student ->{System.out.println(student);});sqlSession.close();}}

通过测试得知,简单类型对于mybatis来说都是可以自动类型识别的:

  • 也就是说对于mybatis来说,它是可以自动推断出ps.setXxxx()方法的。ps.setString()还是ps.setInt()。它可以自动推断。

其实SQL映射文件中的配置比较完整的写法是:

<select id="selectByName" resultType="student" parameterType="java.lang.String">select * from t_student where name = #{name, javaType=String, jdbcType=VARCHAR}
</select>

其中sql语句中的javaType,jdbcType,以及select标签中的parameterType属性,都是用来帮助mybatis进行类型确定的。不过这些配置多数是可以省略的。因为mybatis它有强大的自动类型推断机制。

  • javaType:可以省略
  • jdbcType:可以省略
  • parameterType:可以省略

根据name查。使用完整写法:

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.mybatis.mapper;import com.rainbowsea.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;public interface StudentMapper {
// 单个参数上的处理/*** 当接口中的方法的参数只有一个(单个参数),并且参数的数据类型都是简单类型* 根据id查询,name查询,birth查询,sex查询*/List<Student> selectByName(String name);}
public interface StudentMapper {
// 单个参数上的处理/*** 当接口中的方法的参数只有一个(单个参数),并且参数的数据类型都是简单类型* 根据id查询,name查询,birth查询,sex查询*/List<Student> selectByName(String name);}

Java程序测试,编写

在这里插入图片描述

package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.StudentMapper;
import com.rainbowsea.mybatis.pojo.Student;
import com.rainbowsea.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;public class TestStudentMapper {@Testpublic void testSelectByName() {SqlSession sqlSession = SqlSessionUtil.openSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);List<Student> students = mapper.selectByName("李华");students.forEach(student ->{System.out.println(student);});sqlSession.close();}}

**如果参数只有一个的话,#{} 里面的内容就随便写了。对于 ${} 来说,注意加单引号。关于 #{} 与 ${}的区别的更多内容,大家可以移步至:✏️✏️✏️ **

4.2 单个(一个) Map集合 作为参数

需求:根据name和age查询

在这里插入图片描述


import com.rainbowsea.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;public interface StudentMapper {
// 单个参数上的处理/*** 保存学生信息,通过Map参数,以下是单参数,但是参数类型不是简单类型,是Map集合*/int insertStudentByMap(Map<String, Object> map);}

注意:这种方式是手动封装Map集合,将每个条件以 key 和 value 的形式存放到集合中。然后在使用的时候通过 #{map集合的key}来取值(#{} 中的值一定要是 map 集合当中的 key 值,不然是无法取到值的,这里我为了更加明显的突出这一点,使用了中文作为 map 集合当中的 key)。

在这里插入图片描述

 @Testpublic void testInsertStudentByMap() throws ParseException {SqlSession sqlSession = SqlSessionUtil.openSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);Map<String, Object> map = new HashMap<>();map.put("姓名","赵六");map.put("年龄",20);map.put("身高",1.83);map.put("性别",'男');SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");Date birth = simpleDateFormat.parse("2020-09-09");map.put("生日",birth);mapper.insertStudentByMap(map);sqlSession.commit();sqlSession.close();}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.StudentMapper"><insert id="insertStudentByMap" parameterType="map">insert into t_student (id,name,age,sex,birth,height)values (null,#{姓名},#{年龄},#{性别},#{生日},#{身高});</insert></mapper>

java运行测试

在这里插入图片描述

4.3 单个(一个) 实体类POJO作为参数

需求:插入一条Student数据

在这里插入图片描述

package com.rainbowsea.mybatis.mapper;import com.rainbowsea.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;public interface StudentMapper {
// 单个参数上的处理/*** 保存学生信息,通过PoJO参数,Student是单个参数,但不是简单类型* @param student* @return*/int insertStudentByPOJO(Student student);}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.StudentMapper"><insert id="insertStudentByPOJO" parameterType="Student">insert into t_student (id,name,age,sex,birth,height)values (null,#{name},#{age},#{sex},#{birth},#{height});</insert>
</mapper>

这里需要注意的是:#{} 里面写的是属性名字。这个属性名其本质上是:set/get方法名去掉set/get之后的名字。

运行测试:

在这里插入图片描述

5. 多个参数

根据 name 和 sex 查询 Student 信息

如果是多个参数,mybatis 框架底层是怎么做的呢?

mybatis 框架会自动创建一个map集合,并且map集合是以

这种方式存储参数的

map.put(“arg0”,name)

map.put(“arg1”,sex)

map.put(“param1”,name)

map.put(“param2”,sex)

需求:通过name和sex查询

在这里插入图片描述

这里我们先就用 和我们参数名一样的 name, sex 使用传给 #{} 试试。

在这里插入图片描述

在这里插入图片描述

异常信息描述了:name参数找不到,可用的参数包括[arg1, arg0, param1, param2]

修改StudentMapper.xml配置文件:尝试使用[arg1, arg0, param1, param2]去参数

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.StudentMapper"><!--    多个参数--><select id="selectByNameAndSex" resultType="Student">select id,name,age,height,birth,sexfrom t_studentwhere name = #{arg0} and sex = #{arg1}</select></mapper>

运行测试:

在这里插入图片描述


import com.rainbowsea.mybatis.mapper.StudentMapper;
import com.rainbowsea.mybatis.pojo.Student;
import com.rainbowsea.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class TestStudentMapper {/*** 根据 name 和 sex 查询 Student 信息* 如果是多个参数,mybatis 框架底层是怎么做的呢?*  mybatis 框架会自动创建一个map集合,并且map集合是以*  这种方式存储参数的*  map.put("arg0",name)*  map.put("arg1",sex)*  map.put("param1",name)*  map.put("param2",sex)***/@Testpublic void TestSelectByNameAndSex(){SqlSession sqlSession = SqlSessionUtil.openSession();// mapper 实际上指向了代理对象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);// mapper是代理对象// selectByNameAndSex是代理方法List<Student> students = mapper.selectByNameAndSex("李华", '男');students.forEach(student -> {System.out.println(student);});sqlSession.close();}
}

再将其改为 where name = #{param1} and sex = #{param2} 试试

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.StudentMapper"><!--    多个参数--><select id="selectByNameAndSex" resultType="Student">select id,name,age,height,birth,sexfrom t_studentwhere name = #{param1} and sex = #{param2}</select><!--    where name = #{arg0} and sex = #{arg1}--><!--    where name = #{param1} and sex = #{param2}-->
</mapper>

在这里插入图片描述

改为 arg0 和 param2 混合使用:where name = #{arg0} and sex = #{param2}

在这里插入图片描述

运行也是成功的;

在这里插入图片描述

通过测试可以看到:

  • 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}

根据 name 和 sex 查询 Student 信息
* 如果是多个参数,mybatis 框架底层是怎么做的呢?
* mybatis 框架会自动创建一个map集合,并且map集合是以
* 这种方式存储参数的
* map.put(“arg0”,name)
* map.put(“arg1”,sex)
* map.put(“param1”,name)
* map.put(“param2”,sex)

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

5.1 @Param注解(命名参数)

可以不用arg0 arg1 param1 param2吗?这个map集合的 key我们自定义可以吗?

当然可以。使用 @Param 注解即可。这样可以增强可读性。

如下:

在这里插入图片描述

直接将其定义在参数的位置上,由于 注解的值为 value 时,可以省略属性名

在这里插入图片描述

需求:通过name和sex查询

package com.rainbowsea.mybatis.mapper;import com.rainbowsea.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Param;import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;public interface StudentMapper {/*** 使用Param注解* mybatis框架底层的实现原理* @param name* @param sex* @return*/List<Student> selectByNameAndSex2(@Param(value = "name") String name, @Param("sex") Character sex);}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.StudentMapper"><!--    多个参数--><select id="selectByNameAndSex2" resultType="Student">select id,name,age,height,birth,sexfrom t_studentwhere name = #{name} and sex = #{sex}</select><!--    where name = #{arg0} and sex = #{arg1}--><!--    where name = #{param1} and sex = #{param2}-->
<!--    使用 @Param 注解
注意:使用了@Param注解之后,arg0和arg1失效了,
而 param1和 param2 还可以用
-->
</mapper>

注意:使用了@Param注解之后,arg0和arg1失效了,而 param1和 param2 还可以用

Java程序编写测试:

在这里插入图片描述

import com.rainbowsea.mybatis.mapper.StudentMapper;
import com.rainbowsea.mybatis.pojo.Student;
import com.rainbowsea.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class TestStudentMapper {/*** 根据 name 和 sex 查询 Student 信息* 如果是多个参数,mybatis 框架底层是怎么做的呢?*  mybatis 框架会自动创建一个map集合,并且map集合是以*  这种方式存储参数的*  map.put("arg0",name)*  map.put("arg1",sex)*  map.put("param1",name)*  map.put("param2",sex)***/@Testpublic void TestSelectByNameAndSex(){SqlSession sqlSession = SqlSessionUtil.openSession();// mapper 实际上指向了代理对象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);// mapper是代理对象// selectByNameAndSex是代理方法List<Student> students = mapper.selectByNameAndSex2("李华", '男');students.forEach(student -> {System.out.println(student);});sqlSession.close();}
}

注意的是:不仅select 查询中可以用 @Param ,其它的增删改查,涉及多个参数,自定义参数名的都可以使用 @Param 注解。

6. @Param 注解源码分析

在这里插入图片描述

下面我们进行 DeBug 调试看看。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

7. 总结:

  1. 告诉mybatis框架,我这个方法的参数类型是什么类型的,mybatis 框架自身带有类型自动推断的机制,所以大部分情况下 parameterType 属性都是可以省略不写的。

  2. 其实对于Mybatis 框架来说,简单类型对于mybatis来说都是可以自动类型识别的:

    在MyBatis 框架当中如下,为的类型被定义为简单类型

    简单类型包括:

    • byte short int long float double char

    • Byte Short Integer Long Float Double Character

    • String

    • java.util.Date

    • java.sql.Date

    • 也就是说对于mybatis来说,它是可以自动推断出ps.setXxxx()方法的。ps.setString()还是ps.setInt()。它可以自动推断。

    • 其实SQL映射文件中的配置比较完整的写法是:

      <select id="selectByName" resultType="student" parameterType="java.lang.String">select * from t_student where name = #{name, javaType=String, jdbcType=VARCHAR}
      </select>
      

      其中sql语句中的javaType,jdbcType,以及select标签中的parameterType属性,都是用来帮助mybatis进行类型确定的。不过这些配置多数是可以省略的。因为mybatis它有强大的自动类型推断机制。

      • javaType:可以省略
      • jdbcType:可以省略
        • parameterType:可以省略
  3. 指定 select 查询,返回的结果集,封装到哪里,哪个对象当中。

  4. 对于特殊的(不是简单)类型,POJO是无法自行推断的出来的,需要我们指定比如(集合,POJO类等)

  5. 注意:这种方式是手动封装Map集合,将每个条件以 key 和 value 的形式存放到集合中。然后在使用的时候通过 #{map集合的key}来取值(#{} 中的值一定要是 map 集合当中的 key 值,不然是无法取到值的)。

  6. 传的是POJO类时,需要注意的是:#{} 里面写的是属性名字。这个属性名其本质上是:set/get方法名去掉set/get之后的名字。

  7. 多个参数:mybatis 框架会自动创建一个map集合,并且map集合是以

    这种方式存储参数的

    map.put(“arg0”,name)

    map.put(“arg1”,sex)

    map.put(“param1”,name)

    map.put(“param2”,sex)

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

  1. 注意:使用了@Param注解之后,arg0和arg1失效了,而 param1和 param2 还可以用
  2. 注意的是:不仅select 查询中可以用 @Param ,其它的增删改查,涉及多个参数,自定义参数名的都可以使用 @Param 注解。

8. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/351364.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++_0基础_讲解7 练习

这一讲我为大家准备了几道题目&#xff0c;大家试着独自做一下&#xff08;可能来自不同网站&#xff09; 整数大小比较 - 洛谷 题目描述 输入两个整数&#xff0c;比较它们的大小。若 x>yx>y &#xff0c;输出 > &#xff1b;若 xyxy &#xff0c;输出 &#xff…

【Java04】引用变量数组初始化的内存机制

引用类型数组指向的元素也是引用。其本质是&#xff1a; 由一个在栈上的引用数组变量指向一块堆内存&#xff1b;这块堆内存里存储的元素是引用&#xff0c;又分别指向其他堆内存。 class Person // Person是一个自定义的类 {public int age;puiblic double height;public vo…

集合查询-并(UNION)集运算、交(INTERSECT)集运算、差(EXCEPT)集运算

一、概述 集合查询是对两个SELECT语句的查询结果进行再进行处理的查询 二、条件 1、两个SELECT语句的查询结果必须是属性列数目相同 2、两个SELECT语句的查询结果必须是对应位置上的属性列必须是相同的数据类型 三、并(UNION)运算 1、语法格式&#xff1a; SELECT 语句1…

【论文速读,找找启发点】2024/6/16

ICME 2023 End-To-End Part-Level Action Parsing With Transformer 类似 DETR&#xff0c;通过 加 query的方式实现 端到端 ELAN: Enhancing Temporal Action Detection with Location Awareness 如何实现位置感知&#xff1f; > 重叠的卷积核&#xff1f; Do we really …

ubuntu18.04离线源制作

给客户部署有时需要纯内网环境&#xff0c;那这样就连不了网络。 一些包就下载不下来&#xff0c;而大家都知道用deb离线安装是非常麻烦的&#xff0c;各种依赖让你装不出来。 这里教大家打包源。 我准备2台机器&#xff0c;42和41 42可以联网&#xff0c;41不能联网。我想在…

抓包工具 Wireshark 的下载、安装、使用、快捷键

目录 一、什么是Wireshark&#xff1f;二、Wireshark下载三、Wireshark安装四、Wireshark使用4.1 基本使用4.2 过滤设置1&#xff09;捕获过滤器2&#xff09;显示过滤器 4.3 过滤规则1&#xff09;捕获过滤器-规则语法2&#xff09;显示过滤器-规则语法 4.4 常用的显示过滤器规…

Spring Security 与 JWT、OAuth 2.0 整合详解:构建安全可靠的认证与授权机制

Spring Security 与 OAuth 2.0 整合详解&#xff1a;构建安全可靠的认证与授权机制 将 JWT&#xff08;JSON Web Token&#xff09;与 OAuth 2.0 整合到 Spring Security 中可以为应用程序提供强大的认证和授权功能。以下是详细的整合步骤和代码示例。 1. 引入依赖 首先&am…

Docker:在DockerHub上创建私有仓库

文章目录 Busybox创建仓库推送镜像到仓库 本篇开始要学习在DockerHub上搭建一个自己的私有仓库 Busybox Busybox是一个集成了三百多个最常用Linux命令和工具的软件&#xff0c;BusyBox包含了很多工具&#xff0c;这里拉取该镜像推送到仓库中&#xff1a; 安装 apt install …

2012-2022年各省新质生产力指数数据(含原始数据+结果)

2012-2022年各省新质生产力指数数据&#xff08;含原始数据结果&#xff09; 1、时间&#xff1a;2012-2022年 2、指标&#xff1a;province、year、平均受教育年限、劳动者人力资本结构、高等院校在校学生结构、人均GDP元、在岗职工工资&#xff1a;元、三产从业人员比重、机…

python读取excel导入数据库

一、环境准备&#xff0c;安装包 pip install pandas openpyxl sqlalchemy二、数据准备 三、代码编写 from sqlalchemy import create_engine import pandas as pdclass GDPDataImporter:def __init__(self, db_type, dbapi, host, port, database, username, password):&quo…

[渗透测试学习] Runner-HackTheBox

Runner-HackTheBox 信息搜集 nmap扫描端口 nmap -sV -v 10.10.11.13扫描结果如下 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0) 80/tcp open http nginx 1.18.0 (Ubuntu) 8000…

Linux:线程池

Linux&#xff1a;线程池 线程池概念封装线程基本结构构造函数相关接口线程类总代码 封装线程池基本结构构造与析构初始化启动与回收主线程放任务其他线程读取任务终止线程池测试线程池总代码 线程池概念 线程池是一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影…

AIRNet模型使用与代码分析(All-In-One Image Restoration Network)

AIRNet提出了一种较为简易的pipeline&#xff0c;以单一网络结构应对多种任务需求&#xff08;不同类型&#xff0c;不同程度&#xff09;。但在效果上看&#xff0c;ALL-In-One是不如One-By-One的&#xff0c;且本文方法的亮点是batch内选择patch进行对比学习。在与sota对比上…

React基础教程(07):条件渲染

1 条件渲染 使用条件渲染&#xff0c;结合TodoList案例&#xff0c;进行完善&#xff0c;实现以下功能&#xff1a; 当列表中的数据为空的时候&#xff0c;现实提示信息暂无待办事项当列表中存在数据的时候&#xff0c;提示信息消失 这里介绍三种实现方式。 注意这里的Empty是…

考研计组chap3存储系统

目录 一、存储器的基本概念 80 1.按照层次结构 2.按照各种分类 &#xff08;41&#xff09;存储介质 &#xff08;2&#xff09;存取方式 &#xff08;3&#xff09;内存是否可更改 &#xff08;4&#xff09;信息的可保存性 &#xff08;5&#xff09;读出之后data是否…

HTTP协议 快速入门

http概述 无状态性&#xff1a;HTTP是一个无状态协议&#xff0c;这意味着服务器不会在请求之间保存任何会话信息。每个请求都是独立的&#xff0c;服务器不会记住之前的请求。 请求-响应模型&#xff1a;HTTP通信是基于客户端发送请求和服务器返回响应的模型。客户端&#xf…

Python | 中心极限定理介绍及实现

统计学是数据科学项目的重要组成部分。每当我们想从数据集的样本中对数据集的总体进行任何推断&#xff0c;从数据集中收集信息&#xff0c;或者对数据集的参数进行任何假设时&#xff0c;我们都会使用统计工具。 中心极限定理 定义&#xff1a;中心极限定理&#xff0c;通俗…

Android低代码开发 - InputMenuPanelItem详解

我们知道MenuPanel是一个菜单面板容器&#xff0c;它里面可以放各式各样的菜单和菜单组。今天我们就来详细讲解输入菜单这个东西。 InputMenuPanelItem源码 package dora.widget.panel.menuimport android.content.Context import android.text.Editable import android.text…

系统集成项目管理工程师第9章思维导图发布

今天发布系统集成项目管理工程师新版第9章脑图的图片版

Nintex流程平台引入生成式人工智能,实现自动化革新

工作流自动化提供商Nintex宣布在其Nintex流程平台上推出一系列新的人工智能驱动改进。这些增强显著减少了文档化、管理和自动化业务流程所需的时间。这些新特性为Nintex流程平台不断扩展的人工智能能力增添了新的亮点。 Nintex首席产品官Niranjan Vijayaragavan表示&#xff1a…