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. 总结:
告诉mybatis框架,我这个方法的参数类型是什么类型的,mybatis 框架自身带有类型自动推断的机制,所以大部分情况下 parameterType 属性都是可以省略不写的。
其实对于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:可以省略
指定 select 查询,返回的结果集,封装到哪里,哪个对象当中。
对于特殊的(不是简单)类型,POJO是无法自行推断的出来的,需要我们指定比如(集合,POJO类等)
注意:这种方式是手动封装Map集合,将每个条件以 key 和 value 的形式存放到集合中。然后在使用的时候通过 #{map集合的key}来取值(#{} 中的值一定要是 map 集合当中的 key 值,不然是无法取到值的)。
传的是POJO类时,需要注意的是:#{} 里面写的是属性名字。这个属性名其本质上是:set/get方法名去掉set/get之后的名字。
多个参数:mybatis 框架会自动创建一个map集合,并且map集合是以
这种方式存储参数的
map.put(“arg0”,name)
map.put(“arg1”,sex)
map.put(“param1”,name)
map.put(“param2”,sex)
注意:使用mybatis3.4.2之前的版本时:要用#{0}和#{1}这种形式。
- 注意:使用了@Param注解之后,arg0和arg1失效了,而 param1和 param2 还可以用 。
- 注意的是:不仅select 查询中可以用 @Param ,其它的增删改查,涉及多个参数,自定义参数名的都可以使用 @Param 注解。
8. 最后:
“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”
相关文章:
MyBatis 参数上的处理的细节内容
1. MyBatis 参数上的处理的细节内容 文章目录 1. MyBatis 参数上的处理的细节内容2. MyBatis 参数上的处理3. 准备工作4. 单个(一个)参数4.1 单个(一个)简单类型作为参数4.2 单个(一个) Map集合 作为参数4.3 单个(一个) 实体类POJO作为参数 5. 多个参数5.1 Param注解(命名参数)…...
水帘降温水温
不同环境下的水帘啊,使用水温是不一样的,夏天使用水疗的水有两种,一个是常温的循环水,20~26左右,另外一个呢,就是深井水,重点是啥呢?就是无论我们用哪一种,能够把温度降到…...
kafka如何保证消息不丢失
Kafka发送消息是异步发送的,所以我们不知道消息是否发送成功,所以会可能造成消息丢失。而且Kafka架构是由生产者-服务器端-消费者三种组成部分构成的。要保证消息不丢失,那么主要有三种解决方法。 生产者(producer)端处理 生产者默认发送消息…...
流媒体学习之路(WebRTC)——音频NackTracker优化思路(8)
流媒体学习之路(WebRTC)——音频NackTracker优化思路(8) —— 我正在的github给大家开发一个用于做实验的项目 —— github.com/qw225967/Bifrost目标:可以让大家熟悉各类Qos能力、带宽估计能力,提供每个环节关键参数调节接口并实…...
Java基础面试重点-2
21. JVM是如何处理异常(大概流程)? 如果发生异常,方法会创建一个异常对象(包括:异常名称、异常描述以及异常发生时应用程序的状态),并转交给JVM。创建异常对象,并转交给…...
【活动文章】通用大模型VS垂直大模型,你更青睐哪一方
垂直大模型和通用大模型各有其特定的应用场景和优势。垂直大模型专注于特定领域,提供深度的专业知识和技能,而通用大模型则具备广泛的适用性和强大的泛化能力。以下是一些垂直大模型和通用大模型的例子: 垂直大模型 BERT-Financial…...
记录一个Qt调用插件的问题
问题背景 使用Qt主程序插件的方式开发,即主程序做成一个框,定义好插件接口,然后主程序上通过插件接口与插件进行交互。调试过程中遇到了两个问题,在这里记录一下。 问题1(信号槽定义) 插件与主程序之间&am…...
9.1 Go 接口的定义
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
易于上手的requests
Python中的requests库主要用于发送HTTP请求并获取响应结果。在现代网络编程中,HTTP请求是构建客户端与服务器之间通信的基础。Python作为一种高级编程语言,其丰富的库支持使得它在网络数据处理领域尤为突出。其中,requests库以其简洁、易用的…...
【QT Creator软件】解决中文乱码问题
QT Creator软件解决中文乱码问题 问题描述:Qtcreator安装好后打印中文在控制台输出乱码 在网上也查找了修改编辑器的默认编码为UTF-8,但是仍然没有任何作用,于是有了以下的解决方案 原因剖析:因为项目的编码与控制台的编码不一致…...
边缘网关在智能制造工厂中的创新应用及效果-天拓四方
在数字化浪潮席卷之下,智能制造工厂正面临着前所未有的数据挑战与机遇。边缘网关,作为数据处理与传输的关键节点,在提升工厂运营效率、确保数据安全方面发挥着日益重要的作用。本文将通过一个具体案例,详细阐述边缘网关在智能制造…...
Django-filter
准备工作 首先,确保你已经安装了django-filter包。如果没有,请使用以下命令安装: pip install django-filter然后,在你的settings.py文件中添加django_filters到INSTALLED_APPS列表中: INSTALLED_APPS [# ...djang…...
文字悬停效果
文字悬停效果 效果展示 CSS 知识点 CSS 变量使用回顾-webkit-text-stroke 属性的运用与回顾 页面整体结构实现 <ul><li style"--clr: #e6444f"><a href"#" class"text">First</a></li><li style"--cl…...
[SWPUCTF 2022 新生赛]ez_1zpop(php反序列化之pop链构造)
[SWPUCTF 2022 新生赛]ez_ez_unserialize <?php class X {public $x __FILE__;function __construct($x){$this->x $x; }function __wakeup(){if ($this->x ! __FILE__) {$this->x __FILE__; }}function __destruct(){highlight_file($this->x);//flag is…...
2-1基于matlab的拉普拉斯金字塔图像融合算法
基于matlab的拉普拉斯金字塔图像融合算法,可以使部分图像模糊的图片清楚,也可以使图像增强。程序已调通,可直接运行。 2-1 图像融合 拉普拉斯金字塔图像融合 - 小红书 (xiaohongshu.com)...
Android基础-进程间通信
在Android系统中,跨进程通信(IPC,Inter-Process Communication)是实现不同应用程序或同一应用程序中不同进程间数据共享和交互的关键技术。Android提供了多种IPC机制,每种机制都有其特定的使用场景和优缺点。下面将详细…...
【微信小程序】uni-app 配置网络请求
原因 由于平台的限制,小程序项目中 不支持axios,而且原生的,wx.request()API功能较为简单,不支持拦截器等全局定制的功能。因此,建议在uni-app项目中使用 escook/request-miniprogram 第三方包发起网络数据请求。 步…...
SpringCash
文章目录 简介引入依赖常用注解application.yml使用1. 启动类添加注解使用方法上添加注解 简介 Spring Cache是一个框架,实现了基于注解的缓存功能底层可以使用EHCache、Caffeine、Redis实现缓存。 注解一般放在Controller的方法上,CachePut 注解一般有…...
小红书的文案是怎么写的?有啥套路么!
小红书文案是有自己的调性的,为什么别人的笔记轻轻松松就是爆款,而自己写的笔记却没有人看呢,小红书文案写作有啥套路? 接下来伯乐网络传媒给大家讲一讲,小红书文案写作揭秘:抄作业、拆解产品到种草笔记结…...
开放平台接口安全验证
文章目录 开放平台接口安全验证I 加签方式说明1.1 签名生成的通用步骤1.2 生成随机数算法1.3 举例1.4 签名校验工具II Header参数说明III 业务接口返回结构说明开放平台接口安全验证 统一使用sign签名验证,签名规则也会在本文档中,详细说明。请大家认真阅读。 向平台申请密码…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
