详解Mybatis之参数传递问题

news2024/9/25 11:18:53

编译软件:IntelliJ IDEA 2019.2.4 x64
操作系统:win10 x64 位 家庭版
Maven版本:apache-maven-3.6.3
Mybatis版本:3.5.6


目录

  • 一. Mybatis中参数传递问题
    • 1.1 单个普通参数传递
    • 1.2 多个普通参数传递
    • 1.3 命名参数
    • 1.4 POJO(java Bean)参数传递
    • 1.5 Map参数传递
    • 1.6 Collection ,List & Array等参数传递
  • 二. Mybatis参数传递中#与$的使用问题
    • 2.1 #与$的区别
    • 2.2 #与$的使用场景


一. Mybatis中参数传递问题

1.1 单个普通参数传递

对于单个普通参数而言,只要它的数据类型是Java基本数据类型,包装类型,字符串类型等。请放心大胆的使用它去传递,因为MyBatis可直接使用这个参数,不需要经过任何处理。且不受参数名称约束,即你可以任意命名,但一般遵循见名知意的原则。

示例代码如下:

<select id="selectUsers" resultType="User">
  select id, username, password
  from users
  where id = #{id}
</select>

在上述代码中,"#{id}"中的id可以任意取名,并且在程序中传给id的参数,其数据类型只要是符合(Java基本数据类型,包装类型,字符串类型)其中之一,MyBatis可直接使用这个参数传入到sql语句中。

1.2 多个普通参数传递

对于任意多个参数而言,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,或arg0,arg1。相应的value是参数的值。

用法案例:根据员工姓名与薪资在数据库中查找相应的员工信息

①先在Mapper接口定义根据员工姓名与薪资查找相应的员工信息的方法

代码示例如下:

//根据员工姓名与员工薪资来查查找相应的员工
public Employee selectEmployeeByNameandSalary(String lastName,double salary);

②在映射文件中定义相关的sql

<select id="selectEmployeeByNameandSalary" resultType="mybatis.pojo.Employee">
    select
        id,
        last_name ,
        email,
        salary
    from
        tbl_employee
    where last_name=#{param1}
          and
          salary=#{param2}
</select>

③测试

@Test
public void test2(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        Employee employee = employeeMapper.selectEmployeeByNameandSalary("李四", 9000);
        System.out.println(employee);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

在这里插入图片描述

1.3 命名参数

语法:

@Param(value="参数名")
@Param("参数名")

位置:

在XXXMapper接口中方法的形参前面声明

注意:

  • 它的底层封装的是Map结构
  • 命名参数支持参数【param1,param2,…】,但不支持【arg0,arg1…】

示例代码:

①Mapper接口对应代码的书写

//根据员工姓名与员工薪资来查查找相应的员工
public List<Employee> showEmpByName(@Param("lName") String lastName,@Param("salary") double salary);

②接口对应的映射文件中书写的sql

版本一(参数不使用param1,param2):

<select id="showEmpByName" resultType="mybatis.pojo.Employee">
    select
    id,
        last_name ,
        email,
        salary
    from
        tbl_employee
    //#{lName}里是Mapepr接口中对应方法形参中@Param("lName")里的值    
    where 
    	last_name=#{lName}
    and
        salary=#{salary}
</select>

版本二(参数使用param1,param2):

 <select id="showEmpByName" resultType="mybatis.pojo.Employee">
        select
            id,
            last_name ,
            email,
            salary
        from
            tbl_employee
        where
            last_name=#{param1}
        and
            salary=#{param2}
    </select>

版本三(参数使用arg0,arg1)

 <select id="showEmpByName" resultType="mybatis.pojo.Employee">
        select
        id,
            last_name ,
            email,
            salary
        from
            tbl_employee
        where
            last_name=#{arg0}
        and
            salary=#{arg1}
    </select>

③测试

	@Test
    public void test4(){
        try {
            //从当前类下寻找并加载mybatis-config.xml(核心配置文件)
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

            //通过SqlSessionFactory对象调用openSession()获取sqlsession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //sqlsession对象使用getMapper(),传入EmployeeMapper的反射对象以获取代理对象
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

            //使用其代理对象调用showEmpByName()通过员工姓名与薪资去查找相应的员工
            List<Employee> jack = employeeMapper.showEmpByName("jack", 9000);
            System.out.println(jack);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

1.4 POJO(java Bean)参数传递

Mybatis支持POJO [Java Bean】入参,参数key是POjO中的属性

用法案例:基于1.2小结中的用法案例,修改Mapper接口中该方法的形参为Employee类型,仅修改映射文件中相应的sql与测试代码

①修改Mapper接口中该方法的形参类型为Employee

代码示例如下:

//根据员工姓名与员工薪资来查查找相应的员工
public Employee selectEmployeeByNameandSalary(Employee employee);

②修改映射文件中相应的sql

<select id="selectEmployeeByNameandSalary" resultType="mybatis.pojo.Employee">
    select
        id,
        last_name ,
        email,
        salary
    from
    	tbl_employee
    where 
    	last_name=#{lastName}
   and
    	salary=#{salary}
</select>

③测试

@Test
public void test3(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        Employee employee=new Employee();
        employee.setSalary(5600.0);
        employee.setLastName("jack");

        Employee jack = employeeMapper.selectEmployeeByNameandSalary(employee);

        System.out.println(jack);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

在这里插入图片描述

1.5 Map参数传递

Mybatis支持Map集合类型的元素直接入参,map的key是参数的key

注意:

Mybatis不支持方法重载,因为在Mybatis中xxxMapper接口对应的映射文件中若存在相同方法的sql,则其id值不能保持唯一性,会发生冲突

用法案例:基于1.2节的案例,这次使用Map集合作为形参传入,在对应的映射文件中书写相应的sql并测试

代码示例如下:

①使用Map集合作为形参传入

//根据员工姓名与员工薪资来查查找相应的员工
public List<Employee> showEmpByMap(Map<String,Object> map);

②在对应的映射文件中书写相应的sql

<select id="showEmpByMap" resultType="mybatis.pojo.Employee">
    select
        id,
        last_name ,
        email,
        salary
    from
    tbl_employee
    where last_name=#{lastName} and  salary=#{salary}
</select>

③测试

@Test
public void test5() {
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        Map<String,Object> map=new HashMap<>();
        map.put("lastName","jack");
        map.put("salary",5600);

        List<Employee> jack = employeeMapper.showEmpByMap(map);
        System.out.println(jack);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

在这里插入图片描述

1.6 Collection ,List & Array等参数传递

当传入的参数数据类型为 Collection ,List 或Array等,在对应映射文件的相应sql部分可直接使用mybatis对应的内置自定义类型别名(collection、list、array)传入,亦可使用命名参数自定义名称。

用法案例:通过多个id获取员工的信息 【EmpIds:员工id的集合】

代码示例如下:

a.在EmployeeMapper接口定义相应的方法

/**
 * 通过多个id获取员工的信息 【EmpIds:员工id的集合】
 * @param EmpIds
 * @return
 */
public List<Employee> selectEmpByIds(@Param("ids") List<Integer> EmpIds);

b.在EmployeeMapper接口对应的映射文件中定义相应的sql

 <select id="selectEmpByIds" resultType="employee">
        SELECT
            `id`,
            `last_name`,
            `email`,
            `salary`,
            `dept_id`
        FROM
            `tbl_employee`
        <where>
            `id` in
            (
            <foreach collection="ids" item="id" separator=",">
                #{id}
            </foreach>
            )
        </where>
    </select>

c.测试

@Test
public void test04(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        List<Employee> employees = employeeMapper.selectEmpByOneOpr(1);
        System.out.println(employees);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

在这里插入图片描述


二. Mybatis参数传递中#与$的使用问题

2.1 #与$的区别

  • #底层执行SQL语句的对象,使用PreparedStatementd,预编译SQL,防止SQL注入安全隐患,相对比较安全。
  • $底层执行SQL语句的对象使用Statementi对象,未解决SQL注入安全隐患,相对不安全。

2.2 #与$的使用场景

以查询SQL为例:

select col,col2 from table1 where col=? and col2=group by? order bylimit?,?

使用场景:

  • “#”使用场景:在上述Sql中的占位符位置均可以使用#
  • “$”使用场景:#解决不了的参数传递问题,均可以交给$处理【如form动态表格】

示例代码如下:

public List<Employee> selectEmpByDynamitTable(@Param("tblName")String tblName);
<select id="selectEmpByDynamitTable" resultType="employee">
	SELECT
        id,
        last_name,
        email,
        salary
	FROM
		${tb1Name}
</select>

附注:

在 Mybatis 中,$ 符号也是用于访问各种参数、变量等的值和信息的符号,主要用于动态 SQL 的构建和参数传递等场景中,例如:

  • ${variable}:用于插入变量或者表名/列名等的动态语句部分
  • #{parameter}:用于占位符参数的预编译语句
  • $方法名():用于调用 SQL 片段中定义的方法并返回结果

为什么说${variable}主要用于插入动态语句的部分?

解析不同:

  • ${variable}它是将传入的参数值直接显示在原来的sql语句中,且不加任何引号

    例如slect * from users where id= v a r i a b l e ,传入 {variable},传入 variable,传入{1} => id=1

    代码示例如下:

     <select id="showEmpByMap" resultType="mybatis.pojo.Employee">
            select
                id,
                last_name ,
                email,
                salary
            from
            tbl_employee
            where last_name=${lastName} and  salary=${salary}
        </select>
    
    

    在这里插入图片描述
    在这里插入图片描述

  • #{variable}是将传入的参数值当成一个字符串且加双引号显示

    例如slect * from users where id= v a r i a b l e ,传入 {variable},传入 variable,传入{1} => id=“1”

    代码示例如下:

     <select id="showEmpByMap" resultType="mybatis.pojo.Employee">
            select
                id,
                last_name ,
                email,
                salary
            from
            tbl_employee
            where last_name=#{lastName} and  salary=#{salary}
        </select>
    

    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL知识学习02(MySQL索引详解)

1、索引介绍&#xff1f; 索引是一种用于快速查询和检索数据的数据结构&#xff0c;其本质可以看成是一种排序好的数据结构。 索引的作用就相当于书的目录。打个比方: 我们在查字典的时候&#xff0c;如果没有目录&#xff0c;那我们就只能一页一页的去找我们需要查的那个字&…

鸿蒙Hi3861学习四-Huawei LiteOS介绍

一、什么是LitesOS Huawei LiteOS是华为针对物联网领域推出的轻量级物联网操作系统&#xff0c;是华为物联网战略的重要组成部分&#xff0c;具备轻量级、低功耗、互联互通、组件丰富、快速开发等关键能力。基于物联网领域业务特征打造领域性技术栈&#xff0c;为开发者提供“一…

MEET开发者 | 从无代码小白到大神,95后精神小伙的职场初体验

「无代码开发者故事」第一期的嘉宾是一位初入职场的95后&#xff0c;他保留了白羊座直率、热情的孩子天性&#xff0c;即便长期驻场也能“苦中作乐”&#xff0c;发挥自己旅游和摄影的爱好。初入职场的他在项目中主要承担需求分析的角色&#xff0c;2021年初受公司委派学习和评…

VR全景展示--探索无限可能

随着科技的发展&#xff0c;虚拟现实&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;技术逐渐成为人们关注的焦点。VR技术使得人们可以在虚拟现实中体验到与现实世界不同的感官体验。在VR全景展示中&#xff0c;观众可以通过虚拟现实技术&#xff0c;沉浸式地感受到…

指针函数和函数指针

本文目录 • 前言 • 一、返回指针的函数 二、指向函数的指针回到顶部 一、返回指针的函数 指针也是C语言中的一种数据类型&#xff0c;因此一个函数的返回值肯定可以是指针类型的。 返回指针的函数的一般形式为&#xff1a;类型名 * 函数名(参数列表) 比如下面这个函数&#…

用手机号码归属地 API 开发的应用推荐

引言 手机号码归属地 API是一种提供手机号码归属地信息的接口&#xff0c;通过该接口&#xff0c;可以获取手机号码所属的省份、城市、运营商等信息。它可以帮助企业更好地了解客户&#xff0c;为个性化推荐和精准广告投放提供数据支持。作为一种数据服务&#xff0c;手机号码…

打造高可用、高效的Nginx反向代理应用 - 实战篇

前言 &#x1f3e0;个人主页&#xff1a;我是沐风晓月 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是沐风晓月&#xff0c;阿里云社区博客专家&#x1f609;&#x1f609; &#x1f495; 座右铭&#xff1a; 先努力成长自己&#xff0c;再帮助更多的人 &#xff0c…

快排代码原理实现

参考博客&#xff1a;快速排序算法详解&#xff08;原理、实现和时间复杂度&#xff09; 排序算法的思想非常简单&#xff0c;在待排序的数列中&#xff0c;我们首先要找一个数字作为基准数&#xff08;这只是个专用名词&#xff09;。为了方便&#xff0c;我们一般选择第 1 个…

Java每日一练(20230504)

目录 1. 位1的个数 &#x1f31f; 2. 移除元素 &#x1f31f; 3. 验证二叉搜索树 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 位1的个数 编写一个…

推荐一个免费GIF动图下载的网站

在开发过程中难免遇到耗时操作,耗时操作往往导致线程阻塞,通常这种情况可以采用开线程的方式解决,即将耗时操作放入新线程中,同时在UI线程中加一个GIF动图即可。可作为后端开发工程师来讲单独设计一个GIF图实在是意义不大(懒+不会)。 好在现在发现了这个GIF免费下载的网站…

存储器(二)

目录 一、RAM 1.RAM特点 2.静态RAM 2.1静态RAM保存原理 2.2静态RAM基本单元电路的构成 2.3静态RAM读写操作 3.动态RAM 3.1动态RAM保存原理 3.2动态RAM基本单元电路的构成 3.3动态RAM对单元电路的读写操作 3.4动态RAM的刷新 4.静态RAM与动态RAM的比较 二、ROM 1.ROM…

WinForm对话框详解:信息框、文件对话框、功能对话框

文章目录 信息框文件对话框功能对话框 对话框是开发中经常用到的控件&#xff0c;甚至在上古的MFC编程中&#xff0c;默认就是把一个对话框编辑成窗口。winForm提供了多种不同的对话框&#xff0c;包括信息框、文件对话框、功能对话框等&#xff0c;下面逐个演示这些消息框。 …

欧姆龙PLC仿真环境搭建及通信测试

前言 欧姆龙PLC是工控领域市场率较高的品牌之一&#xff0c;有低端CP/CH系列&#xff0c;中端CJ系列&#xff0c;高端NX/NJ系列。对于上位机开发来说&#xff0c;主要的协议有Hostlink协议、FinsTCP/UDP协议、EtherNetIP协议&#xff0c;今天主要跟大家分享一下&#xff0c;我…

《互联网安全产品漏洞管理规定》

《网络产品安全漏洞管理规定》由工业和信息化部、国家互联网信息办公室、公安部联合印发&#xff0c;自2021年9月1日起施行。 该《规定》明确&#xff0c;任何组织或者个人不得利用网络产品安全漏洞从事危害网络安全的活动&#xff0c;不得非法收集、出售、发布网络产品安全漏洞…

图片png怎么转成pdf格式?

图片png怎么转成pdf格式&#xff1f;相信很多上班的小伙伴们都会遇到类似的问题&#xff0c;需要将公司的图片宣传册等资料发送给客户&#xff0c;但是公司宣传册本身是一页一页的图片文件&#xff0c;如果这样发送了就显得很不专业或者说比较杂乱&#xff01;所以&#xff0c;…

scrapy 爬虫中间件的学习

Scrapy中间件是一个处理Scrapy请求和响应的机制。中间件可以在请求或响应被Scrapy引擎处理之前或之后对其进行修改或操作&#xff0c;用于实现诸如缓存、代理、用户代理等功能。 Scrapy中间件的作用主要有以下几个方面&#xff1a; 1、对请求的处理&#xff1a;可以在请求被S…

【Spark练习】RDD分区操作

练习1&#xff1a;行动&#xff08;Action&#xff09;操作算子方法 任务1: reduce // 1. 数组 val x sc.parallelize(List(1,2,3,4)) val y x.reduce( (a,b) > a b) // 2. 列表 val rdd sc.parallelize(List(1,2,3,4)) // 求和,将各个数累加,依次合并 下面两种方式相…

读书笔记// 《数据产品经理》

书名&#xff1a;写给数据产品经理新人的工作笔记 出版时间&#xff1a;2020年10月 本书以数据产品经理角色的定位和合作关系为切入点&#xff0c;站在整个数据体系的视角&#xff0c;从工作流程的角度剖析数据需求沟通和判断的过程、指标体系搭建的过程&#xff0c;同时介绍了…

Swift 中的 async/await ——代码实例详解

前言 async-await 是在 WWDC 2021 期间的 Swift 5.5 中的结构化并发变化的一部分。Swift 中的并发性意味着允许多段代码同时运行。这是一个非常简化的描述&#xff0c;但它应该让你知道 Swift 中的并发性对你的应用程序的性能是多么重要。有了新的 async 方法和 await 语句&am…

《人工智能概论》课程重点总结

目录 遗传算法相关参数问题 种群规模、迭代次数、交叉率、变异率对算法的影响 A*算法中open表和close表的作用 为什么A*算法中open表是增长的 启发式函数h(n)取值的影响 A*算法可以找到最优解的条件 模式识别系统的组成 有监督学习和无监督学习的区别 模型评估三大原则…