在使用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中從而達到我們想要的效果!