MyBaits参数绑定

MyBatis 是一款优秀的==持久层==框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
一款优秀的半自动化的基于ORM思想开发的持久层框架。
多数业务需求下,SQL的操作都需要参数支持。根据需求可以传入单个参数、多个参数、对象参数等。MyBatis对入参的绑定也有一定的要求。下面先回顾一下#{}和${}的区别。
#{}:Mybatis中#传递参数底层使用PreparedStatement对象,使用占位符方式,相对安全。

${}:Mybatis中$传递参数底层使用Statement对象,字符串拼接方式,相对不安全。
Statement:底层传递SQL参数时,使用拼接SQL方式,存在SQL注入安全隐患.
PreparedStatement:底层传递SQL参数时,使用?【占位符】方式,相对安全。

预编译:数据库驱动在发送sql和参数到DBMS之前,先对sql语句进行编译处理,之后DBMS则可以直接对sql进行处理,不需要再次编译,提高了性能。这一点mybatis 默认情况下,将对所有的 sql 进行预编译处理。 预编译可以将多个操作步骤合并成一个步骤,一般而言,越复杂的sql,编译程度也会复杂,难度大,耗时,费性能,而预编译可以合并这些操作,预编译之后DBMS可以省去编译直接运行sql。 预编译语句可以重复利用。 把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。
#{} 提供了更安全的参数处理方式,尤其是在防止SQL注入方面,而 ${} 则适用于简单的字符串替换,但需要注意潜在的安全风险
区别
1、默认单引号
#{} 对应的变量会自动加上单引号
${} 对应的变量不会加上单引号 ,需要手动添加单引号
2、sql注入
#{} 能防止sql 注入
${} 不能防止sql 注入
3、默认参数值
#{} 默认值 arg0、arg1、arg2 或 param1、param2
${} 默认值 param1、param2、param3
mybatis版本不同默认的参数也不同,可以在报错后查看默认的内容!

单一参数

// 持久层接口方法只有一个参数时
Student queryForObject(String no);
<select id="queryForObject" resultType="com.soft.entity.Student">
	<!-- 
		SQL接收参数使用#{参数名}的形式,#{参数名}本质含义是占位符,类似于原生JDBC中的问号。
		MyBatis在给占位符赋值时采用的也是类似远程JDBC中按照问号先后顺序赋值的形式,只匹配占位符的顺序。
		所以当入参只有一个时,#{}中的内容可以任意填,但为了见名知意,这里写了和入参一样的名称
	-->
    select * from student where sno = #{sno}
</select>

多参数

// 持久层接口方法有多个个参数时
Student queryForObject(String sex, String clazz);
<select id="queryForObject" resultType="com.soft.entity.Student">
	<!-- 
		SQL接收参数使用#{参数名}的形式,#{参数名}本质含义是占位符,类似于原生JDBC中的问号。
		MyBatis在给占位符赋值时采用的也是类似远程JDBC中按照问号先后顺序赋值的形式,只匹配占位符的顺序。
		所以当入参只有多个时,#{}中的内容不可以任意填,为了明确参数和占位符的顺序关系,这里需要使用
            #{arg0} #{arg1} arg0代表第一个参数,arg1代表第二个参数,依此类推
            #{param1} #{param2} param1代表第一个参数,param2代表第二个参数,以此类推
		这种带有明确顺序的名称
	-->
    select * from student where sex = #{arg0} and class = #{arg1}
    select * from student where sex = #{param1} and class = #{param2}
</select>
// 持久层接口方法有多个个参数时
// 为了明确参数和占位符的对应关系,MyBatis提供了对参数设置别名的方式。
// 通过@Param("名称")设置参数名称
Student queryForObject(@Param("sex") String sex, @Param("clazz") String clazz);
<select id="queryForObject" resultType="com.soft.entity.Student">
	<!-- 
		设置了参数名称时,可直接通过名称获取值
	-->
    select * from student where sex = #{sex} and class = #{clazz}
</select>

对象参数

单对象

// 持久层接口方法时对象参数时
Student queryForObject(Student student);
<select id="queryForObject" resultType="com.soft.entity.Student">
	<!-- 
		入参是一个对象,#{} 就相当于调用了属性的get 方法。
		MyBatis对入参是对象的情况进行了处理,SQL接收参数直接写实体类中属性的get方法去掉get之后首字母小写即可。
			例如:getSno -> sno
		由于实体类中的set、get方法是通过工具自动生成的,具有规范性,所以有些地方也会说直接填写属性名称。
	-->
    select * from student where sex = #{sex} and class = #{clazz}
</select>

单 + 字面量

// 持久层接口方法时对象参数时
Student queryForObject(@Param("student") Student student, @Param("index") int index, @Param("limit") int limit);
<select id="queryForObject" resultType="com.soft.entity.Student">
	<!-- 
		入参是一个对象,#{} 就相当于调用了属性的get 方法。
		MyBatis对入参是对象的情况进行了处理,SQL接收参数直接写实体类中属性的get方法去掉get之后首字母小写即可。
			例如:getSno -> sno
		由于实体类中的set、get方法是通过工具自动生成的,具有规范性,所以有些地方也会说直接填写属性名称。
	-->
    select * from student where sex = #{student.sex} and class = #{student.clazz}
    limit #{index} #{limit}
</select>

Map 参数

// 持久层接口方法时对象参数时
Student queryForObject(Map<String, Object> map);
<select id="queryForObject" resultType="com.soft.entity.Student">
	<!-- 
		入参是一个Map,#{} 就相当于调用了 map 的get() 方法。所以 #{} 中的值要写 map 的 key。
	-->
    select * from student where sex = #{sex} and class = #{clazz}
</select>

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

别名映射的类型
_bytebyte
_char (since 3.5.10)char
_character (since 3.5.10)char
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
MyBatis 是一个流行的 Java 持久化框架,它可以让开发者更加方便地进行数据库操作。当我们需要把一个列表(array,list)作为参数传递给 MyBatis 时,可以采用以下的两种方式: 第一种方式是使用 `foreach` 元素进行循环,将列表中的元素依次设置到对应的参数中,如下所示: ``` <select id="selectByIds" resultType="User"> select * from user where id in <foreach item="id" collection="list" open="(" separator="," close=")"> #{id} </foreach> </select> ``` 其中,`selectByIds` 是 SQL 语句的 ID,`User` 是返回结果类型。`<foreach>` 元素中,item 表示要遍历的变量,collection 表示要遍历的集合,open、separator、close 分别表示循环开始符、分隔符和结束符。 第二种方式是使用 `Provider` 接口的实现类,把列表转换成字符串类型的传参,代码如下: ``` public class UserSqlProvider { public static String selectByIds(Map<String, Object> map) { List<Integer> ids = (List<Integer>) map.get("list"); StringBuilder builder = new StringBuilder(); builder.append("("); for (int i = 0; i < ids.size(); i++) { builder.append(ids.get(i)); if (i < ids.size() - 1) { builder.append(","); } } builder.append(")"); return builder.toString(); } } ``` 在 `Mapper` 中这样写: ``` @Select("select * from user where id in #{ids}") List<User> selectByIds(@Param("ids") List<Integer> ids); ``` 以上是两种比较常用的传递列表参数的方式,开发者可以根据实际需要来选择适合自己的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值