• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • mybatis框架入門(一)

    標簽: Mybatis  Java  MySQL  mybatis  數據庫  mysql  java


    在這里插入圖片描述



    一、MyBatis簡介


    (一)什么是MyBatis

    MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。

    MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注SQL本身,而不需要花費精力去處理例如注冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。

    Mybatis通過xml或注解的方式將要執行的各種statement(statement、preparedStatemnt)配置起來,并通過java對象和statement中的sql進行映射生成最終執行的sql語句,最后由mybatis框架執行sql并將結果映射成java對象并返回。

    總之,Mybatis對JDBC訪問數據庫的過程進行了封裝,簡化了JDBC代碼,解決JDBC將結果集封裝為Java對象的麻煩。

    下圖是MyBatis架構圖:

    在這里插入圖片描述

    (1)mybatis-config.xml是Mybatis的核心配置文件,通過其中的配置可以生成SqlSessionFactory,也就是SqlSession工廠

    (2)基于SqlSessionFactory可以生成SqlSession對象

    (3)SqlSession是一個既可以發送SQL去執行,并返回結果,類似于JDBC中的Connection對象,也是Mybatis中至關重要的一個對象。

    (4)ExecutorSqlSession底層的對象,用于執行SQL語句

    (5)MapperStatement對象也是SqlSession底層的對象,用于接收輸入映射(SQL語句中的參數),以及做輸出映射(即將SQL查詢的結果映射成相應的結果)

    (二)為什么要使用MyBatis

    思考:在開始之前,思考下如何通過JDBC查詢Emp表中的所有記錄,并封裝到一個List集合中返回。(演示:準備數據、導包、導入JDBC程序)

    1、使用傳統方式JDBC訪問數據庫:

    (1)使用JDBC訪問數據庫有大量重復代碼(比如注冊驅動、獲取連接、獲取傳輸器、釋放資源等);

    (2)JDBC自身沒有連接池,會頻繁的創建連接和關閉連接,效率低;

    (3)SQL是寫死在程序中,一旦修改SQL,需要對類重新編譯;

    (4)對查詢SQL執行后返回的ResultSet對象,需要手動處理,有時會特別麻煩;

    2、使用mybatis框架訪問數據庫:

    (1)Mybatis對JDBC對了封裝,可以簡化JDBC代碼;

    (2)Mybatis自身支持連接池(也可以配置其他的連接池),因此可以提高程序的效率;

    (3)Mybatis是將SQL配置在mapper文件中,修改SQL只是修改配置文件,類不需要重新編譯。

    (4)對查詢SQL執行后返回的ResultSet對象,Mybatis會幫我們處理,轉換成Java對象。

    總之,JDBC中所有的問題(代碼繁瑣、有太多重復代碼、需要操作太多對象、釋放資源、對結果的處理太麻煩等),在Mybatis框架中幾乎都得到了解決!!


    二、MyBatis入門


    (一)準備數據,創建庫和表

    創建yonghedb庫、emp表,并插入若干條記錄

    -- 1、創建數據庫 yonghedb 數據庫
    create database if not exists yonghedb charset utf8;
    use yonghedb; -- 選擇yonghedb數據庫
    -- 2、刪除emp表(如果存在)
    drop table if exists emp;
    -- 3、在 yonghedb 庫中創建 emp 表
    create table emp(
        id int primary key auto_increment,
        name varchar(50),
        job varchar(50),
        salary double
    );
    -- 4、往 emp 表中, 插入若干條記錄
    insert into emp values(null, '王一', '程序員', 3300);
    insert into emp values(null, '齊二', '程序員', 2800);
    insert into emp values(null, '劉三', '程序員鼓勵師', 2700);
    insert into emp values(null, '陳四', '部門總監', 4200);
    insert into emp values(null, '趙五', '程序員', 3000);
    insert into emp values(null, '董六', '程序員', 3500);
    insert into emp values(null, '蒼七', '程序員', 3700);
    insert into emp values(null, '韓八', 'CEO', 5000);
    

    (二)創建工程,導入所需jar包、創建測試類

    1、創建Maven的java工程

    在這里插入圖片描述

    2、導入junit、mysql、mybaits等開發包

    在pom.xml文件中引入相關依賴包即可

    <dependencies>
        <!-- junit單元測試 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
        </dependency>
        <!-- mysql驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <!-- 整合log4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.4</version>
        </dependency>
    </dependencies>
    

    3、創建com.tedu.mybatis.TestMybatis01測試類,并提供findAll方法(查詢emp表中所有的員工信息),開發步驟如下:

    在這里插入圖片描述

    /** 練習1(快速入門): 查詢emp表中的所有員工, 返回一個List<Emp>集合
    * @throws IOException */
    @Test
    public void findAll() throws IOException {
        //1.讀取mybatis的核心配置文件(mybatis-config.xml)
        //2.通過配置信息獲取一個SqlSessionFactory工廠對象
        //3.通過工廠獲取一個SqlSession對象
        //4.通過namespace+id找到要執行的sql語句并執行sql語句
        //5.輸出結果
    }
    

    (三)添加mybatis-config.xml文件

    1、在src/main/resources目錄下,創建mybatis-config.xml文件(MyBatis的核心配置文件)

    在這里插入圖片描述
    2、mybatis-config.xml文件配置如下:

    mybatis-config文件頭信息如下:

    <?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">
        
    <!-- MyBatis的全局配置文件 -->
    <configuration >
    	
    </configuration>
    

    mybatis-config文件詳細配置如下:

    <?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">
        
    <!-- MyBatis的全局配置文件 -->
    <configuration >
    	<!-- 1.配置環境,可配置多個環境(比如:develop開發、test測試) -->
    	<environments default="develop">
    		<environment id="develop">
    			
    			<!-- 1.1.配置事務管理方式:JDBC/MANAGED
    					JDBC:將事務交給JDBC管理(推薦)
    					MANAGED:自己管理事務
    			-->
    			<transactionManager type="JDBC"></transactionManager>
    			
    			<!-- 1.2.配置數據源,即連接池 JNDI/POOLED/UNPOOLED
    						JNDI:已過時
    						POOLED:使用連接池(推薦)
    						UNPOOLED:不使用連接池
    			 -->
    			<dataSource type="POOLED">
    				<property name="driver" value="com.mysql.jdbc.Driver"/>
    				<property name="url" value="jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8"/>
    				<property name="username" value="root"/>
    				<property name="password" value="root"/>
    			</dataSource>
    		</environment>
    	</environments>
    	
    	<!-- 2.導入Mapper配置文件,如果mapper文件有多個,可以通過多個mapper標簽導入 -->
    	<mappers>
    		<mapper resource="EmpMapper.xml"/>
    	</mappers>
    </configuration>
    

    dtd文件時xml的約束文件

    (四)添加EmpMapper.xml文件

    1、在src/main/resources目錄下,創建EmpMapper.xml文件 (實體類的映射文件)

    在這里插入圖片描述

    2、EmpMapper.xml文件配置如下:

    EmpMapper文件頭信息如下:

    <?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值應該保證唯一
    	在程序中通過[ namespace + id ]定位到要執行哪一條SQL語句
     -->
    <mapper namespace="">
    	
    	
    </mapper>
    

    EmpMapper文件詳細配置如下:

    <?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值應該保證唯一
    	在程序中通過[ namespace + id ]定位到要執行哪一條SQL語句
     -->
    <mapper namespace="EmpMapper">
    	<!-- 通過select、insert、update、delete標簽聲明要執行的SQL -->
    	<!-- 練習1: 查詢emp表中的所有員工信息
    		resultType指定查詢的結果將會封裝到什么類型中
    		即使最終返回的結果是集合(List<Emp>),resultType也只需要指定集合中的泛型即可!
     	-->
    	<select id="findAll" resultType="com.tedu.pojo.Emp">
    		select * from emp
    	</select>
    
    </mapper>
    

    (五)添加并編寫Emp實體類

    注意:在當前實例中,Emp類中的屬性和數據庫表的字段名稱必須一致,否則將會無法將結果集封裝到Java對象中。

    在src/main/java目錄下創建 com.tedu.pojo.Emp類,并編輯Emp類:提供私有屬性以及對應的getter方法、setter方法,并重寫toString方法
    (要是添加有參構造函數,就一定要首先添加無參構造函數,否則會報錯)

    package com.tedu.pojo;
    /**
     * 實體類,用于封裝Emp表中的一條用戶信息
     */
    public class Emp {
    	//1.聲明實體類中的屬性
    	private Integer id;
    	private String name;
    	private String job;
    	private Double salary;
    	
    	//2.提供對應的getter和setter方法
    	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 getJob() {
    		return job;
    	}
    	public void setJob(String job) {
    		this.job = job;
    	}
    	public Double getSalary() {
    		return salary;
    	}
    	public void setSalary(Double salary) {
    		this.salary = salary;
    	}
    	
    	//3.重寫toString方法
    	@Override
    	public String toString() {
    		return "Emp [id=" + id + ", name=" + name + ", job=" + job + ", salary=" + salary + "]";
    	}
    }
    

    (六)實現測試類,并測試

    1、實現findAll方法,代碼如下:

    /** 練習1(快速入門):  查詢emp表中的所有員工, 返回一個List<Emp>集合
     * @throws IOException */
    @Test
    public void findAll() throws IOException {
    	//1.讀取mybatis的核心配置文件(mybatis-config.xml)
    	InputStream in = Resources
    			.getResourceAsStream("mybatis-config.xml");
    	//2.通過配置信息獲取一個SqlSessionFactory工廠對象
    	SqlSessionFactory fac = 
    			new SqlSessionFactoryBuilder().build( in );
    	//3.通過工廠獲取一個SqlSession對象
    	SqlSession session = fac.openSession();
    	//4.通過namespace+id找到要執行的sql語句并執行sql語句
    	List<Emp> list = session
    			.selectList("EmpMapper.findAll");
    	//5.輸出結果
    	for(Emp e : list) {
    		System.out.println( e );
    	}
    }
    

    2、執行findAll方法,輸出結果為:

    Emp [id=1, name=王一, job=程序員, salary=3300.0]
    Emp [id=2, name=齊二, job=程序員, salary=2800.0]
    Emp [id=3, name=劉三, job=程序員鼓勵師, salary=2700.0]
    Emp [id=4, name=陳四, job=部門總監, salary=4200.0]
    Emp [id=5, name=趙五, job=程序員, salary=3000.0]
    Emp [id=6, name=董六, job=程序員, salary=3500.0]
    Emp [id=7, name=蒼七, job=程序員, salary=3700.0]
    Emp [id=8, name=韓八, job=CEO, salary=5000.0]
    

    三、MyBatis入門細節


    (一)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">
        
    <!-- MyBatis的全局配置文件 -->
    <configuration >
    	<!-- 1.配置環境,可配置多個環境(比如:develop開發、test測試) -->
    	<environments default="develop">
    		<environment id="develop">
    			
    			<!-- 1.1.配置事務管理方式:JDBC/MANAGED
    			JDBC:將事務交給JDBC管理(推薦)
    			MANAGED:自己管理事務
    			  -->
    			<transactionManager type="JDBC"></transactionManager>
    			
    			<!-- 1.2.配置數據源,即連接池 JNDI/POOLED/UNPOOLED
    				JNDI:已過時
    				POOLED:使用連接池(推薦)
    				UNPOOLED:不使用連接池
    			 -->
    			<dataSource type="POOLED">
    				<property name="driver" value="com.mysql.jdbc.Driver"/>
    				<property name="url" value="jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8"/>
    				<property name="username" value="root"/>
    				<property name="password" value="root"/>
    			</dataSource>
    		</environment>
    	</environments>
    	
    	<!-- 2.導入Mapper配置文件,如果mapper文件有多個,可以通過多個mapper標簽導入 -->
    	<mappers>
    		<mapper resource="EmpMapper.xml"/>
    	</mappers>
    </configuration>
    
    • environments標簽:該標簽內部可以配置多個environment,即多種環境,每種環境可以做不同配置或連接不同數據庫。例如,開發、測試、生產環境可能需要不同的配置,連接的數據庫可能也不相同,因此我們可以配置三個environment,分別對應上面三種不同的環境。

      但是要記住,environment可以配置多個,但是最終要使用的只能是其中一個!

    • environment標簽:內部可以配置多種配置信息,下面介紹事務管理配置和數據源配置。

    • transactionManage標簽:事務管理配置,mybatis中有兩種事務管理方式,也就是 type="[JDBC\|MANAGED]

      • JDBC:這個配置就是直接使用了 JDBC的提交和回滾設置,它依賴于從數據源得到的連接來管理事務范圍。推薦使用。
      • MANAGED:這個配置幾乎沒做什么。它從來不提交或回滾一個連接。需要自己手動添加并管理。不推薦使用。
    • dataSource標簽:數據源,也就是連接池配置。這里type指定數據源類型,有三種內建的類型:JNDIPOOLEDUNPOOLED

      • JNDI:已過時,不推薦使用!
      • POOLED:使用連接池,mybatis會創建連接池,并從連接池中獲取連接訪問數據庫,在操作完成后,將會把連接返回連池。
      • UNPOOLED:不使用連接池,該方式適用于只有小規模數量并發用戶的簡單應用程序上。
    • mappers標簽:用于導入mapper文件的位置,其中可以配置多個mapper,即可以導入多個mapper文件。

    (二)EmpMapper.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值應該保證唯一
    	在程序中通過[ namespace + id ]定位到要執行哪一條SQL語句
     -->
    <mapper namespace="EmpMapper">
    	<!-- 通過select、insert、update、delete標簽聲明要執行的SQL -->
    	<!-- 練習1: 查詢emp表中的所有員工信息
    		resultType指定查詢的結果將會封裝到什么類型中
    		即使最終返回的結果是集合(List<Emp>),resultType也只需要指定集合中的泛型即可!
     	-->
    	<select id="findAll" resultType="com.tedu.pojo.Emp">
    		select * from emp
    	</select>
    
    </mapper>
    

    (1)第1行是xml的文檔聲明,用于聲明xml的版本和編碼

    (2)第2、3、4行,引入了xml約束文檔,當前xml文檔將會按照mybatis-3-mapper.dtd文件所要求的規則進行書寫。

    (3)Mapper標簽:根標簽,其中namespace(名稱空間,也叫命名空間),要求不能重復。在程序中通過[ namespace + id ]定位到要執行哪一條SQL語句

    (4)select標簽:用于指定將來要執行的各種SQL語句。標簽上可以聲明屬性,下面介紹常用的屬性:idresultTyperesultMap

    • id屬性:要求值不能重復。將來在執行SQL時,可以通過[ namespace + id ]找到指定SQL并執行。

    • resultType屬性:從這條SQL語句中返回所期望類型的類的完全限定名稱(包名+類名)。注意如果是集合情形,那應該是集合可以包含的類型,而不能是集合本身。

      簡而言之,resultType控制查詢SQL執行后返回值的類型或集合中的泛型,例如查詢emp表中的單條記錄,返回值是一個Emp對象,因此,resultType="com.tedu.pojo.Emp";

      如果查詢emp表中的多條記錄,返回值是一個List,此時resultType的值應該集合中的泛型,因此resultType="com.tedu.pojo.Emp";

    • resultMap屬性:復雜對象結構(例如多表關聯查詢等)。 使用 resultTyperesultMap,但不能同時使用。


    四、MyBatis增刪改查


    (一)新增員工

    1、編輯EmpMapper.xml文件, 添加新增員工對應的sql.

    <!-- 練習2: 新增員工信息: 趙云 保安 6000
    增刪改的標簽上不用指定resultType, 因為返回值都是int類型
    -->
    <update id="insert" >
    	insert into emp value(null, '趙云', '保安', 6000)
    </update>
    

    2、編寫TestMybatis類,添加testInsert方法,實現新增員工操作。

    /** 練習2: 新增員工信息: 趙云 保安 6000 */
    @Test
    public void testInsert() {
      //執行sql語句, 返回執行結果
      int rows = session.update("EmpMapper.insert");
      //提交事務
      session.commit();
      System.out.println("影響的行數: "+rows);
    }
    

    (二)修改員工

    1、編輯EmpMapper.xml文件, 添加新增員工對應的sql。

    <!-- 練習3:修改員工信息:趙云 保鏢 20000 -->
    <update id="update">
    	update emp set job='保鏢', salary=20000 where name='趙云'
    </update>
    

    2、編寫TestMybatis類,添加testUpdate方法,實現修改員工信息。

    /** 練習3: 修改員工信息, 將趙云的job改為'保鏢',salary改為20000 */
    @Test
    public void testUpdate() {
      //執行sql語句, 返回執行結果
      int rows = session.update("EmpMapper.update");
      //提交事務
      session.commit();
      System.out.println("影響行數:"+rows);
    }
    

    (三)刪除員工

    1、編輯EmpMapper.xml文件, 添加新增員工對應的sql。

    <!-- 練習4: 刪除name為'趙云'的記錄 -->
    <update id="delete">
    	delete from emp where name='趙云'
    </update>
    

    2、編寫TestMybatis類,添加testDelete方法,實現刪除員工。

    /** 練習4: 刪除name為'趙云'的記錄 */
    @Test
    public void testDelete() {
      //執行sql語句, 返回執行結果
      int rows = session.update("EmpMapper.delete");
      //提交事務
      session.commit();
      System.out.println("影響行數:"+rows);
    }
    

    五、mybatis中的占位符


    (一)#{}占位符

    在上面的增刪改查操作中,SQL語句中的值是寫死在SQL語句中的,而在實際開發中,此處的值往往是用戶提交過來的值,因此這里我們需要將SQL中寫死的值替換為占位符。

    在mybatis中占位符有兩個,分別是 #{} 占位符 和 ${} 占位符:

    • #{}:相當于JDBC中的問號(?)占位符,是為SQL語句中的參數值進行占位,大部分情況下都是使用#{}占位符; 并且當#{}占位符是為字符串或者日期類型的值進行占位時,在參數值傳過來替換占位符的同時,會進行轉義處理(在字符串或日期類型的值的兩邊加上單引號)
    • ${}:是為SQL片段進行占位,將傳過來的SQL片段直接拼接在${}占位符所在的位置,不會進行任何的轉義處理。(由于是直接將參數拼接在SQL語句中,因此可能會引發SQL注入攻擊問題)
    • 需要注意的是:使用${}占位符為SQL語句中的片段占位時,即使只有一個參數,也要先將參數封裝再傳遞!
    • 練習5:查詢emp表中指定id的員工信息

    在mapper文件中編寫SQL語句:

    <!-- 練習5: 查詢emp表中指定id的員工信息 -->
    <select id="findById" resultType="com.tedu.pojo.Emp">
    	select * from emp where id=#{id}
    </select>
    

    Java代碼實現:

    /** 練習5: 查詢emp表中指定id的員工信息 */
    @Test
    public void testFindById() {
      //執行sql語句, 返回執行結果
      Emp emp = session.selectOne( "EmpMapper.findById", 1 );
      System.out.println( emp );
    }
    
    • 練習6:新增員工信息: 張飛 Java開發工程師 15000

    在mapper文件中編寫SQL語句:

    <!-- 練習6: 新增員工信息: 張飛 Java開發工程師 15000
      如果通過map集合傳輸參數, 需要保證占位符中的變量名
      和map集合中的key保持一致
      如果通過pojo對象傳輸參數, 需要保證占位符中的變量名
      和對象中的屬性名保持一致, 或者在pojo中有對應的
      getXxx方法
    -->
    <update id="insert2">
    	insert into emp values (null, #{name}, #{job}, #{salary})
    </update>
    

    Java代碼實現:

    /** 練習6: 新增員工信息: 張飛 Java開發工程師 15000 */
    @Test
    public void testInsert2() {
      //將要傳輸的參數封裝到map集合中
      //Map map = new HashMap();
      //map.put("name", "張飛");
      //map.put("job", "Java開發工程師");
      //map.put("salary", 15000);
      //也可以將要傳輸的參數封裝到Emp對象中
      Emp emp = new Emp();
      emp.setName("關羽123");
      emp.setJob("保安");
      emp.setSalary(8000.0);
      //執行sql語句
      intsession rows = session.update("EmpMapper.insert2", emp);
      //提交事務
      session.commit();
      System.out.println( "影響的行數: "+rows );
    }
    
    • 練習7:修改員工信息: 張飛 架構師 25000

    在mapper文件中編寫SQL語句:

    <!-- 練習7: 修改員工信息: 張飛 架構師 25000 -->
    <update id="update2">
      update emp set job=#{job}, salary=#{salary}
      where name=#{name}
    </update>
    

    Java代碼實現:

    /** 練習7: 修改員工信息: 張飛 架構師 25000 */
    @Test
    public void testUpdate2() {
      //將參數封裝到Emp對象中
      Emp emp = new Emp();
      emp.setName("張飛");
      emp.setJob("架構師");
      emp.setSalary(25000.0);
      //執行sql語句
      intsession rows = session.update("EmpMapper.update2", emp);
      //提交事務
      session.commit();
      System.out.println("影響的行數: "+rows);
    }
    
    • 練習8:刪除emp表中指定id的員工信息

    mapper文件配置:

    <!-- 練習8:刪除emp表中指定id的員工信息 -->
    <insert id="delete2" parameterType="String">
    	delete from emp where id=#{id}
    </insert>
    

    java代碼示例:

    /*  練習8:刪除emp表中指定id的員工信息 */
    public void testDelete2() throws IOException{
      ......
      //執行SQL語句
      int rows = session.delete("EmpMapper.delete2", 1);
      //提交事務
      session.commit();
      System.out.println("影響行數:"+rows);
    }
    

    在上面的增刪改查練習中,當SQL語句中包含的參數值是傳遞過來的,在SQL語句中我們會通過#{}占位符進行占位,在SQL語句真正執行時,再將傳遞過來的值替換SQL語句中的占位符。

    其實,#{}就是JDBC中的問號(?)占位符,因此為了安全考慮,在執行時會對傳遞過來的字符串和日期類型高的值進行轉譯處理。

    例如:查詢指定name的員工信息,SQL語句為:

    select * from emp where name=#{name}
    

    其實就等價于JDBC中: select * from emp where name=?

    如果傳過來的參數值為:王海濤,那么最終執行的SQL語句為:

    -- 在參數替換占位符的同時進行了轉義處理(在值的兩邊加上了單引號)
    select * from emp where name='王海濤' 
    

    (二)${}占位符

    那么如果我們在傳遞的時候不是一個參數值,而是一個SQL片段呢?

    例如:在查詢時,我們想動態的傳遞查詢的列:

    select #{columns} from emp
    

    此時傳遞過來的應該是一個SQL片段,不同于上面的參數值,如果此時還用#{},也會像上面一樣被轉譯處理:select 'id,name,job' from emp,這不是我們希望看到的!

    如果不想讓傳過來的SQL片段被轉譯處理,而是直接拼接在SQL語句中,那么這里可以使用${},例如:

    select ${columns} from emp
    

    拼接之后:select id,name,job from emp

    • 練習9:動態指定要查詢的列

    在mapper文件中編寫SQL語句:

    <!-- 練習9: 動態指定要查詢的列 -->
    <select id="findAll2" resultType="com.tedu.pojo.Emp">
    	select ${cols} from emp
    </select>
    

    java代碼示例:

    /** 練習9: 動態指定要查詢的列 */
    @Test
    public void testFindAll2() {
      Map map = new HashMap();
      //map.put("cols", "id, name");
      //map.put("cols", "id, name, salary");
      map.put("cols", "id,name,job,salary");
      //執行sql語句, 返回結果
      List<Emp> list = session.selectList("EmpMapper.findAll2", map);
      //輸出結果
      for ( Emp e : list ) {
      	System.out.println( e );
      }
    }
    
    • 示例2: 根據name模糊查詢emp表

    在mapper文件中編寫SQL語句:

    <!-- 練習10: 根據name模糊查詢emp表 -->
    <select id="findAll3" resultType="com.tedu.pojo.Emp">
      select * from emp
      where name like '%${name}%'
    </select>
    
    <!-- 練習11: 根據name模糊查詢emp表 -->
    <select id="findAll4" resultType="com.tedu.pojo.Emp">
      select * from emp
      where name like #{name}
    </select>
    

    Java代碼實現:

    /**
     * 練習10: 根據name模糊查詢emp表
     * '%王%' '%劉%'
     */
    @Test
    public void testFindAll3() {
      //將參數封裝到map集合中
      Map map = new HashMap();
      map.put("name", "濤");
      //執行sql, 返回結果
      List<Emp> list = session.selectList("EmpMapper.findAll3", map);
      //輸出結果
      for (Emp emp : list) {
      	System.out.println( emp );
      }
    }
    
    /**
     * 練習11: 根據name模糊查詢emp表
     * '%王%' '%劉%'
     */
    @Test
    public void testFindAll4() {
      //將參數封裝到map集合中
      Map map = new HashMap();
      map.put("name", "%劉%");
      //執行sql, 返回結果
      List<Emp> list = session.selectList("EmpMapper.findAll4", map);
      //輸出結果
      for (Emp emp : list) {
      	System.out.println( emp );
      }
    }
    

    需要注意的是,在傳遞 ${} 對應的值時,即使只有一個參數,也需要將值存入map集合中!!

    總結:在大多數情況下還是使用#{}占位符,而${}多用于為SQL片段進行占位!

    版權聲明:本文為qq1808814025原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq1808814025/article/details/106341637

    智能推薦

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    猜你喜歡

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    19.vue中封裝echarts組件

    19.vue中封裝echarts組件 1.效果圖 2.echarts組件 3.使用組件 按照組件格式整理好數據格式 傳入組件 home.vue 4.接口返回數據格式...

    精品国产乱码久久久久久蜜桃不卡