關於Mybatis中Mapper輸入參數的兩種取值符號

在使用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(),

查詢數據正常,接下來,第二個方法調用 queryByName1(),

 查詢失敗,觀察我們mapper中第二個sql語句的書寫

select * from person where name=${name}

在使用${}時,裏面只能是value,否則報錯;因此我們將其改爲value,觀察第三個方法的調用queryByName2(),

此處依舊報錯,觀察我們的mapper文件第三個語句, 

select * from person where name=${value}

其報錯原因是因爲,當有參數傳遞進來時,mapper的${}接收到參數,然後將該sql語句轉爲:

select * from person where name=charleschou

很明顯這是一條錯誤的語句,因爲我們沒單引號,因此程序依舊會報錯,我們需要的sql語句應該是

select * from person where name='charleschou'

因此,觀察第四個方法的調用queryByName3()

執行成功,觀察mapper文件中的最後一個查詢語句,我們手動添加了單引號,因此不報錯

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

 

 

對於兩種參數獲取方式的使用, 這裏再總結一點,使用#{}方式,可以防止sql注入,而${}方式,則不能防止sql注入。

那麼,我們實際開發或者使用中,應該避免使用${}方式嗎?答案是否定的,雖然這種方式不能防注入,也不能自動加單引號,但是它可以用作其他用途,比如在查詢批量數據需要根據字段排序時,我們可以利用此方式動態的將字段傳入到sql中從而達到我們想要的效果!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章