MyBatis——使用#{}與${}獲取參數

1 前言

MyBatis 的映射文件中,獲取參數的方式主要有 #{} 和 ${}。

(1)#{} 與 ${} 的區別

  • #{}:參數佔位符,使用 PreparedStatement 方式操作 SQL,在爲 String 類型變量賦值時,可以自動加單引號,有預編譯,可以防止 SQL 注入;
  • ${}:字符串替換,使用 Statement 方式操作 SQL,在爲 String 類型變量賦值時,需要手動加單引號,沒有預編譯,不可以防止 SQL 注入;

一般建議使用 #{},但在模糊查詢和批量刪除時,建議使用 ${}。由於 #{} 會給 String 類型變量自動加單引號,導致在模糊查詢和批量刪除時出現的問題見→JdbcTemplate

(2)#{} 與 ${} 獲取參數的方法

傳輸參數個數與類型 #{}獲取參數方法 ${}獲取參數方法
1. 單個字面量 可以用任意名字獲取參數值,如:#{xxx} 只能用${value}或${_parameter}獲取
2. 單個JavaBean 可以通過屬性名直接獲取屬性值,如:#{sid} 可以通過屬性名直接獲取屬性值,如:${sid}
3. 單個Map 可以通過鍵的名字獲取值,如:#{key1} 可以通過鍵的名字獲取值,如:${key1}
4. 多個字面量 MyBatis會默認將這些參數放入Map中,並以0,1,2,...或param1,param2,param3,...爲鍵,如:#{0}、#{param1}等 MyBatis會默認將這些參數放入Map中,並以param1,param2,param3,...爲鍵,如:${param1}
5. 多個字面量,被@Param("key")標註 MyBatis會默認將這些參數放入Map中,並以param1,param2,param3,...或@Param("p_id")後的參數爲鍵,如:#{param1}、#{p_id}等 MyBatis會默認將這些參數放入Map中,並以param1,param2,param3,...或@Param("p_id")後的參數爲鍵,如:${param1}、${p_id}
6. List或Array MyBatis會默認將List或Array放入Map中,並以list或array爲鍵 MyBatis會默認將List或Array放入Map中,並以list或array爲鍵

注意:字面量是指 String 和基本數據類型及其封裝類,4和5中同一個值被2個鍵指向,如5中 map 如下,param1 和 p_id 都指向1005,param2 和 p_name 都指向"孫七"。

{p_name=孫七, p_id=1005, param1=1005, param2=孫七}

2 實驗環境

 (1)導入 JAR 包

其中,前2個 jar 包下載地址見 → log4j-1.2.17.jar、 mybatis-3.4.1.jar,將 jar 包放入 lib 目錄下,並選中所有 jar 包,右鍵,選擇【Add to Build Path】。

(2) 工作目錄 

注意:src 和 conf 目錄下的 com.mapper 包必須同名。

(3)配置文件

log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 
	<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
		<param name="Encoding" value="UTF-8" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L)\n" />
		</layout>
	</appender>
 
	<logger name="java.sql">
		<level value="debug" />
	</logger>
 
	<logger name="org.apache.ibatis">
		<level value="info" />
	</logger>
 
	<root>
		<priority value="debug" />
		<appender-ref ref="STDOUT" />
	</root>
</log4j:configuration>

注意:log4j.xml文件名不能隨意更改。   

mybatis-config.xml

<?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="jdbc.properties"></properties>
	
	<!-- 設置連接數據庫的環境,default用於設置默認使用的數據庫環境 -->
	<environments default="mysql">
		<!-- 設置某個具體的數據庫環境 -->
		<environment id="mysql">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	
	<!-- 引入映射文件 -->
	<mappers>
		<package name="com.mapper"/>
	</mappers>
</configuration>

jdbc.properties

# K = V
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/users
jdbc.username=root
jdbc.password=0.

3 案例分析

首先在 MySQL 中創建數據庫:users,再在此數據庫中創建表:students,包含id(int)、name(varchar)和sex(varchar) 3個字段,其中,id 設置了自增,students 表中數據如下:

首先介紹下公共的文件,包含 Student.java、StudentMapper.java、Test.java,不同的是 StudentMapper.xml,將在各章節分別介紹。

Student.java

package com.bean;
 
public class Student {
	private Integer id;
	private String name;
	private String sex;
	
	public Student() {}

	public Student(Integer id, String name, String sex) {
		this.id = id;
		this.name = name;
		this.sex = sex;
	}

	public Integer getId() {
		return id;
	}
	
	public void setId(Integer id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getSex() {
		return sex;
	}
	
	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", sex=" + sex + "]";
	}
}

StudentMapper.java

package com.mapper;
 
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import com.bean.Student;
 
public interface StudentMapper {
	//1. 單個字面量
	public Student getStudentById(Integer id);
	
	//2. 單個JavaBean
	public Student getStudentByBean(Student student);
	
	//3. 單個Map
	public Student getStudentByMap(Map<String,Object> map);
	
	//4. 多個字面量
	public Student getStudentByIdAndName(Integer id,String name);
	
	//5. 多個字面量,被@Param("key")標註
	public Student getStudentByParam(@Param("p_id")Integer id,@Param("p_name")String name);
}

Test.java

package com.test;
 
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
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.bean.Student;
import com.mapper.StudentMapper;
 
public class Test {
	
	public static void main(String[] args) throws IOException {
		InputStream is=Resources.getResourceAsStream("mybatis-config.xml");
		SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
		SqlSession sqlSession=sqlSessionFactory.openSession(true); //自動提交事務
		//getMapper:會通過動態代理動態生成StudentMapper的代理實現類
		StudentMapper mapper=sqlSession.getMapper(StudentMapper.class);
		
		//1. 單個字面量
		Student student1=mapper.getStudentById(1001);
		System.out.println(student1);
		
		//2. 單個JavaBean
		Student student=new Student(1002,"李四",null);
		Student student2=mapper.getStudentByBean(student);
		System.out.println(student2);
		
		//3. 單個Map
		Map<String,Object> map=new HashMap();
		map.put("id", 1003);
		map.put("name", "王五");
		Student student3=mapper.getStudentByMap(map);
		System.out.println(student3);
		
		//4. 多個字面量
		Student student4=mapper.getStudentByIdAndName(1004,"週六");
		System.out.println(student4);
		
		//5. 多個字面量,被@Param("key")標註
		Student student5=mapper.getStudentByParam(1005,"孫七");
		System.out.println(student5);
	}
}

3.1 #{} 方式獲取參數

StudentMapper.xml

<?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.mapper.StudentMapper">
	<!-- 1.單個字面量:public Student getStudentById(Integer id); -->
	<select id="getStudentById" resultType="com.bean.Student">
		select * from students where id = #{xxx}
	</select>
	
	<!-- 2.單個JavaBean:public Student getStudentByBean(Student student); -->
	<select id="getStudentByBean" resultType="com.bean.Student">
		select * from students where id = #{id} and name = #{name}
	</select>
	
	<!-- 3.單個Map:public Student getStudentByMap(Map<Integer,String> map); -->
	<select id="getStudentByMap" resultType="com.bean.Student">
		select * from students where id = #{m_id} and name = #{m_name}
	</select>
	
	<!-- 4.多個字面量:public Student getStudentByIdAndName(Integer id,String name); -->
	<select id="getStudentByIdAndName" resultType="com.bean.Student">
		select * from students where id = #{0} and name = #{1}
		<!-- select * from students where id = #{param1} and name = #{param2} -->
	</select>
	
	<!-- 5.多個字面量,被@Param("key")標註:public Student getStudentByParam(@Param("sid")Integer id,@Param("sname")String name); -->
	<select id="getStudentByParam" resultType="com.bean.Student">
		select * from students where id = #{p_id} and name = #{p_name}
		<!-- select * from students where id = #{param1} and name = #{param2} -->
	</select>
</mapper>

控制檯輸出如下: 

DEBUG 06-12 22:44:16,593 ==>  Preparing: select * from students where id = ?  
Student [id=1001, name=張三, sex=男]
DEBUG 06-12 22:44:16,638 ==>  Preparing: select * from students where id = ? and name = ?  
Student [id=1002, name=李四, sex=女]
DEBUG 06-12 22:44:16,639 ==>  Preparing: select * from students where id = ? and name = ?  
Student [id=1003, name=王五, sex=男]
DEBUG 06-12 22:44:16,641 ==>  Preparing: select * from students where id = ? and name = ?  
Student [id=1004, name=週六, sex=女]
DEBUG 06-12 22:44:16,645 ==>  Preparing: select * from students where id = ? and name = ?  
Student [id=1005, name=孫七, sex=男]

3.2 ${} 方式獲取參數

StudentMapper.xml

<?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.mapper.StudentMapper">
	<!-- 1.單個字面量:public Student getStudentById(Integer id); -->
	<select id="getStudentById" resultType="com.bean.Student">
		select * from students where id = ${value}
		<!-- select * from students where id = ${_parameter} -->
	</select>
	
	<!-- 2.單個JavaBean:public Student getStudentByBean(Student student); -->
	<select id="getStudentByBean" resultType="com.bean.Student">
		select * from students where id = ${id} and name = '${name}'
	</select>
	
	<!-- 3.單個Map:public Student getStudentByMap(Map<Integer,String> map); -->
	<select id="getStudentByMap" resultType="com.bean.Student">
		select * from students where id = ${m_id} and name = '${m_name}'
	</select>
	
	<!-- 4.多個字面量:public Student getStudentByIdAndName(Integer id,String name); -->
	<select id="getStudentByIdAndName" resultType="com.bean.Student">
		select * from students where id = ${param1} and name = '${param2}'
	</select>
	
	<!-- 5.多個字面量,被@Param("key")標註:public Student getStudentByParam(@Param("sid")Integer id,@Param("sname")String name); -->
	<select id="getStudentByParam" resultType="com.bean.Student">
		select * from students where id = ${p_id} and name = '${p_name}'
		<!-- select * from students where id = ${param1} and name = '${param2}' -->
	</select>
</mapper>

控制檯輸出如下:

DEBUG 06-12 22:52:30,543 ==>  Preparing: select * from students where id = 1001
Student [id=1001, name=張三, sex=男]
DEBUG 06-12 22:52:30,594 ==>  Preparing: select * from students where id = 1002 and name = '李四'
Student [id=1002, name=李四, sex=女]
DEBUG 06-12 22:52:30,597 ==>  Preparing: select * from students where id = 1003 and name = '王五'
Student [id=1003, name=王五, sex=男]
DEBUG 06-12 22:52:30,600 ==>  Preparing: select * from students where id = 1004 and name = '週六'
Student [id=1004, name=週六, sex=女]
DEBUG 06-12 22:52:30,604 ==>  Preparing: select * from students where id = 1005 and name = '孫七'
Student [id=1005, name=孫七, sex=男]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章