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 configuration
        PUBLIC "-//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;
    }


    @Override
    public 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 mapper
        PUBLIC "-//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, sex
        from t_student
        where 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 {

    @Test
    public 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 mapper
        PUBLIC "-//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, sex
        from t_student
        where birth = #{birth}
    </select>


    <select id="selectBySex" resultType="Student">
        select id, name, age, height, birth, sex
        from t_student
        where sex = #{sex}
    </select>

</mapper>

Java程序测试,编写

根据 brith 查询

在这里插入图片描述

    //java.util.Date; java.sql.Date 他们在mybatis当中都是为简单类型
    @Test
    public 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 {


    @Test
    public 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 {

    @Test
    public 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)。

在这里插入图片描述

 @Test
    public 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 mapper
        PUBLIC "-//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 mapper
        PUBLIC "-//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 mapper
        PUBLIC "-//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,sex
        from t_student
        where 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)
     *
     *
     */
    @Test
    public 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 mapper
        PUBLIC "-//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,sex
        from t_student
        where 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 mapper
        PUBLIC "-//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,sex
        from t_student
        where 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)
     *
     *
     */
    @Test
    public 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. 最后:

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机相关专业的探讨

目录 一、计算机相关专业是否仍是“万金油”选择 二、计算机行业的未来发展态势 三、从专业与个人的匹配度判断选择计算机相关专业 四、对于高考生的建议 一、计算机相关专业是否仍是“万金油”选择 计算机相关专业在过去很长一段时间内确实被视为“万金油”专业&#xff0…

算法训练营day06--242.有效的字母异位词+349. 两个数组的交集+202. 快乐数+1. 两数之和

一、242.有效的字母异位词 题目链接&#xff1a;https://leetcode.cn/problems/valid-anagram/description/ 文章讲解&#xff1a;https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html 视频讲解&#xff1a;http…

电视剧推荐

1、《春色寄情人》 2、《唐朝诡事录》 3、《南来北往》 4、《与凤行》 5、《利剑玫瑰》 6、《承欢记》

【教程】使用立创EDA打开JSON格式的PCB及原理图

这里写目录标题 一、将PCB和原理图放同一文件夹二、打开嘉立创EDA并导入.zip文件三、选择.zip文件并选择 “导入文件并提取库” 一、将PCB和原理图放同一文件夹 并打包成.zip文件 二、打开嘉立创EDA并导入.zip文件 嘉立创 我这里用的网页端&#xff0c;客户端下载页面拉到…

html的网页制作代码分享

<!-- prj_8_2.html --> <!DOCTYPE html> <html lang "EN"><head><meta charset"utf-8" /><title>页面布局设计</title><style type "text/css">*{padding: 0px;margin:0px;}#header{back…

Spring中IOC容器

IoC IOC容器 IoC是一种设计思想&#xff0c;面向对象编程 Spring通过IoC管理所有Java对象的实例化和初始化&#xff0c;控制对象之间依赖关系 将IoC容器管理的Java对象称为Spring Bean&#xff0c;与new创建的对象没有区别 控制反转&#xff08;IoC Inversion of Controle&a…

世优科技AI数字人多模态交互系统“世优波塔”正式发布

2024年6月6日&#xff0c;世优科技“波塔发布会”在北京举办&#xff0c;本次发布会上&#xff0c;世优科技以全新的“波塔”产品诠释了更高效、更智能、更全面的AI数字人产品及软硬件全场景解决方案&#xff0c;实现了世优品牌、产品和价值的全面跃迁。来自行业协会、数字产业…

大众点评全国丽人POI采集225万家-2024年5月底

大众点评全国丽人POI采集225万家-2024年5月底 店铺POI点位示例&#xff1a; 店铺id Hav6zIYtzhyyopIZ 店铺名称 防屏蔽 十分制服务评分 8.9 十分制环境评分 8.9 十分制划算评分 8.9 人均价格 210 评价数量 19935 店铺地址 建北一支路观音桥步行街红鼎国际A座9-9 店铺…

英伟达GPU对比分析:A100、A800、H100与H800

在当今技术迅速发展的时代&#xff0c;英伟达的GPU产品线提供了多种高性能选项&#xff0c;以满足不同类型的工作负载需求。本文将对英伟达的四种GPU型号——A100、A800、H100和H800进行深入对比分析&#xff0c;探讨它们在性能、架构、应用场景等方面的差异&#xff0c;以帮助…

LIN 入门(1)

1、概述 LIN 是什么 LIN 是 Local Interconnect Network 的缩写&#xff0c;是基于 UART/SCI(Universal Asynchronous Receiver-Transmitter / Serial Communication Interface&#xff0c;通用异步收发器/串行通信接口)的低成本串行通信协议。可用于汽车、家电、办 公设备等…

代码随想录-二叉树 | 111 二叉树的最小深度

代码随想录-二叉树 | 111 二叉树的最小深度 LeetCode 111 二叉树的最小深度解题思路代码难点总结 LeetCode 111 二叉树的最小深度 题目链接 代码随想录 题目描述 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说…

讯飞星火模型-语音转文字实现

目录 项目结构 准备音频 接口Demo 准备代码&#xff08;完整修改后&#xff09; 测试提取中文文字代码 结果 下载链接&#xff1a; 这是上周打算试试&#xff0c;提取视频文字之后&#xff0c;制作视频字幕&#xff0c;从而想用大模型来实现&#xff0c;基本的demo可以在…

图像的混合与渐进变换

1.实验目的 平常我们看到的美图秀秀等两个图片混合是怎么生成的呢&#xff0c;今天我们看看图像处理关于这部分怎么做的&#xff1f; 2.实验条件 pycharm python编译器 3.实验代码 # File: 图像混合与渐进变换.py # Author: chen_song # Time: 2024/6/11 下午6:08 "…

CorelDRAW® Graphics Suite 全新 2024 专业图形设计软件

CorelDRAW Graphics Suite 是配备齐全的专业设计工具包&#xff0c;可以非常高的效率提供令人惊艳的矢量插图、布局、照片编辑和排版项目。价格实惠的订阅获得令人难以置信的持续价值&#xff0c;即时、有保障地获得独家的新功能和内容、一流的性能&#xff0c;以及对最新技术的…

【C语音 || 数据结构】二叉树--堆

文章目录 前言堆1.1 二叉树的概念1.2 满二叉树和完美二叉树1.3 堆的概念1.4 堆的性质1.4 堆的实现1.4.1堆的向上调整算法1.4.1堆的向下调整算法1.4.1堆的接口实现1.4.1.1堆的初始化1.4.1.2堆的销毁1.4.1.3堆的插入1.4.1.4堆的删除1.4.1.4堆的判空1.4.1.4 获取堆的数据个数 前言…

轻松玩转新商业模式:工会排队!

在当今数字化时代&#xff0c;互联网的蓬勃发展不仅重塑了商业模式&#xff0c;也深刻改变了消费者的购物习惯。传统的实体零售店面与在线销售平台正面临着巨大的市场挑战。然而&#xff0c;正是这些变革为品牌提供了新的发展机遇。通过创新的商业模式和有效的私域流量管理&…

弱监督语义/实例/全景分割综述2022

摘要 我们从一个统一的角度总结了现有的高效标签图像分割方法&#xff0c;讨论了一个重要的问题:如何弥合弱监督和密集预测之间的差距——目前的方法大多是基于启发式先验&#xff0c;如跨像素相似性、跨标签约束、跨视图一致性和跨图像关系。最后&#xff0c;对标签高效深度图…

纷享销客海外合规观点与方案:个人隐私数据保护与数据出入境

出海&#xff0c;已不再是企业的“备胎”&#xff0c;而是必须面对的“大考”&#xff01;在这个全球化的大潮中&#xff0c;有的企业乘风破浪&#xff0c;勇攀高峰&#xff0c;也有的企业在异国他乡遭遇了“水土不服”。 面对“要么出海&#xff0c;要么出局”的抉择&#xf…

大功率回馈式负载:行业竞争态势

随着科技的不断发展&#xff0c;大功率回馈式负载在各个行业中的应用越来越广泛。大功率回馈式负载是一种能够将电能回馈到电网的设备&#xff0c;具有节能、环保、高效等优点。然而&#xff0c;随着市场竞争的加剧&#xff0c;大功率回馈式负载行业也面临着诸多挑战。 首先&am…

同城信息房产出租小程序源码系统 完全开源可二次开发 带完整的安装代码包以及搭建教程

系统概述 在数字化转型的浪潮中&#xff0c;房产租赁市场也迎来了新的发展机遇。随着移动互联网的普及&#xff0c;越来越多的用户倾向于通过手机应用或小程序来寻找合适的租房信息。为了满足这一需求&#xff0c;小编给大家分享一款“同城信息房产出租小程序源码系统”&#…