在使用Mybatis框架时,我们会使用Mapper配置文件来定义sql语句以实现我们所需要的增删改查。而对于sql语句中所需要的参数的传递,是一个非常常见的问题,在jdbc中我们可以使用PreparedStatement来传递我们所需要的参数。在Mybatis中,我们使用parameterType来传递输入参数(如果觉得此处唠叨,就当凑个字数)。

而对于参数来说,我们平常常见的就是八大基本类型+String。在Mapper中,我们利用书写 #{ }或者${ }来在SQL 中获取我们传来的参数,那么,二者有什么区别呢?接下来就是我个人对其的一些总结:

1.若传递的参数为8大基本类型或者String,如果使用#{ }的方式,在花括号中可以填入任意参数名都可以,例如

<mapper namespace="com.charles.mybatis.personMapper">
		<select id="selectPersonById" resultType="com.charles.mybatis.person" parameterType="int">
			select * from person where id = #{AnyParaName}
		</select>
	</mapper>

2.若传递的参数为8大基本类型或者String,如果使${ }的方式,在花括号中必须填入value,例如

<mapper namespace="com.charles.mybatis.personMapper">
		<select id="selectPersonById" resultType="com.charles.mybatis.person" parameterType="int">
			select * from person where id = #{value}
		</select>
	</mapper>

3.若传入参数为对象类型,使用#{ }和${ }都需要传入对象的属性名,例如

<mapper namespace="com.charles.mybatis.personMapper">
		<select id="com.charles.mybatis.person" resultType="com.charles.mybatis.person" parameterType="int">
			select * from person where id = #{id}
		</select>
	</mapper>

4.两者都可以支持对象的级联属性。

 

5.在使用String数据类型作为参数时,#{}自动为其添加双引号,${}原样输出,不添加任何东西。接下来,用一个小demo来具体操作一下,验证其正确性。

 

建立pojo person.java

package com.charles.mybatis;

public class person {
	private int id;
	private String name;
	public person(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public person() {
		super();
	}
	@Override
	public String toString() {
		return "person [id=" + id + ", name=" + name + "]";
	}
	

}

建立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>
	<properties resource="db.properties"></properties>
		<typeAliases>
			<package name="com.charles.pojo"/>
		</typeAliases>
		<typeHandlers>
			 <typeHandler handler="com.charles.converter.StringAndIntConverter" javaType="String" jdbcType="INTEGER"/>	
		</typeHandlers>
	<environments default="development">
	
		<environment id="development">
		<transactionManager type="JDBC"/>
		<dataSource type="POOLED">
				<property name="driver" value="${driver}"/>
				<property name="url" value="${url}"/>
				<property name="username" value="${username}"/>
				<property name="password" value="${password}"/>
		</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="com/charles/pojo/personMapper.xml"/>
	</mappers>
</configuration>

建立数据库配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis
username=root
password=charles

建立mapper代理接口

package com.charles.mapper;
import java.util.List;
import com.charles.pojo.person;
public interface personMapper {
	person queryByName(String name);
	person queryByName1(String name);
	person queryByName2(String name);
	person queryByName3(String name);

}

之后,建立mapper配置文件,定义了四个查询语句,每一个的参数使用形式不同,观察其执行。

<?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">
	<mapper namespace="com.charles.mapper.personMapper">
	
	<select id="queryByName" parameterType="String" resultType="person">
		select * from person where name=#{name}
	</select>

	<select id="queryByName1" parameterType="String" resultType="person">
		select * from person where name=${name}
	</select>

	<select id="queryByName2" parameterType="String" resultType="person">
		select * from person where name=${value}
	</select>

	<select id="queryByName3" parameterType="String" resultType="person">
		select * from person where name='${value}'
	</select>	
			<resultMap type="person" id="personResultMap">
				 <id property="id" column="id" javaType="String" jdbcType="INTEGER"/>
				 <result property="name" column="name"/>
			</resultMap>
	</mapper>

最后,创建一个测试类,完成demo的测试,分别执行main方法里面的四个函数调用,观察执行结果

package com.charles.pojo;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.charles.mapper.personMapper;

public class test
{
	public static void main(String[] args) throws IOException 
	{
//		queryByName("charleschou");
//		queryByName1("charleschou");
//		queryByName2("charleschou");
//		queryByName3("charleschou");
	}
	public static void queryByName(String name) throws IOException
	{
		Reader reader=Resources.getResourceAsReader("conf.xml");
		SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=build.openSession();
		personMapper mapper = session.getMapper(personMapper.class);
		person queryByName = mapper.queryByName("charleschou");
		System.out.println(queryByName);
	}
	public static void queryByName1(String name) throws IOException
	{
		Reader reader=Resources.getResourceAsReader("conf.xml");
		SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=build.openSession();
		personMapper mapper = session.getMapper(personMapper.class);
		person queryByName = mapper.queryByName1("charleschou");
		System.out.println(queryByName);
	}
	public static void queryByName2(String name) throws IOException
	{
		Reader reader=Resources.getResourceAsReader("conf.xml");
		SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=build.openSession();
		personMapper mapper = session.getMapper(personMapper.class);
		person queryByName = mapper.queryByName2("charleschou");
		System.out.println(queryByName);
	}
	public static void queryByName3(String name) throws IOException
	{
		Reader reader=Resources.getResourceAsReader("conf.xml");
		SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=build.openSession();
		personMapper mapper = session.getMapper(personMapper.class);
		person queryByName = mapper.queryByName3("charleschou");
		System.out.println(queryByName);
	}
	

}

(我的数据库此时是有数据的),观察执行结果,第一个方法调用queryByName(),

springboot mybatis map作为入参_xml

查询数据正常,接下来,第二个方法调用 queryByName1(),

springboot mybatis map作为入参_xml_02

 查询失败,观察我们mapper中第二个sql语句的书写

select * from person where name=${name}

在使用${}时,里面只能是value,否则报错;因此我们将其改为value,观察第三个方法的调用queryByName2(),

springboot mybatis map作为入参_mybatis_03

此处依旧报错,观察我们的mapper文件第三个语句, 

select * from person where name=${value}

其报错原因是因为,当有参数传递进来时,mapper的${}接收到参数,然后将该sql语句转为:

select * from person where name=charleschou

很明显这是一条错误的语句,因为我们没单引号,因此程序依旧会报错,我们需要的sql语句应该是

select * from person where name='charleschou'

因此,观察第四个方法的调用queryByName3()

springboot mybatis map作为入参_参数传值_04

执行成功,观察mapper文件中的最后一个查询语句,我们手动添加了单引号,因此不报错

select * from person where name='${value}'

 

 

对于两种参数获取方式的使用, 这里再总结一点,使用#{}方式,可以防止sql注入,而${}方式,则不能防止sql注入。

那么,我们实际开发或者使用中,应该避免使用${}方式吗?答案是否定的,虽然这种方式不能防注入,也不能自动加单引号,但是它可以用作其他用途,比如在查询批量数据需要根据字段排序时,我们可以利用此方式动态的将字段传入到sql中从而达到我们想要的效果!