Mybatis最詳細入門

1. 框架概述

1.1 什麼是框架

能夠說,一個框架是一個可複用的設計構件,它規定了應用的體系結構,闡明瞭整個設計、協做構件之間的依賴關係、責任分配和控制流程,表現爲一組抽象類以及其實例之間協做的方法,它爲構件複用提供了上下文(Context)關係。所以構件庫的大規模重用也須要框架。html

1.2 爲何使用框架

  • 由於軟件系統發展到今天已經很複雜了,特別是服務器端軟件,涉及到的知識,內容,問題太多。java

  • 在某些方面使用別人成熟的框架就至關於讓別人幫你完成一些基礎工做,你只須要集中精力完成系統的業務邏輯設計mysql

  • 並且框架通常是成熟,穩健的,它能夠處理系統不少細節問題,好比,事務處理,安全性,數據流控制等問題。git

  • 還有框架通常都通過不少人使用,因此結構很好,因此擴展性也很好,並且它不斷升級的,你能夠直接享受別人升級代碼帶來的好處程序員

1.3 軟件開發的三層架構

  • 咱們用三層結構主要是使項目結構更清楚,分工更明確,有利於後期的維護和升級.github

  • 三層架構包含:表現層業務層持久化層sql

     

2. MyBatis介紹

2.1 MyBatis概述

  • MyBatis參考網址:http://www.mybatis.org/mybatis-3/zh/index.html數據庫

  • MyBatis什麼?apache

    • MyBatis是一個優秀的持久層框架,它是一個半自動化的ORM框架編程

    • 使用JDBC操做數據庫的過程進行封裝,使開發者只須要關注 SQL 自己,而不須要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。

  • MyBatis由來?

    • MyBatis 本是apache的一個開源項目iBatis

    • 2010年這個項目由apache software foundation 遷移到了google code,而且更名爲MyBatis 。

    • 2013年11月遷移到Github。

  • Mybatis在哪寫SQL語句?如何設置SQL參數和封裝查詢結果?

    • Mybatis經過XML註解的方式,將要執行的各類statement(statement、preparedStatemnt、CallableStatement)配置起來。

    • 並經過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射成java對象並返回。

2.2 JDBC示例代碼

public class JDBCTest {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;

try {
// 加載數據庫驅動
Class.forName("com.mysql.jdbc.Driver");

// 經過驅動管理類獲取數據庫連接connection = DriverManager
connection = DriverManager.getConnection(
                          "jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
                       "root",
                            "root"
            );

// 定義sql語句 ?表示佔位符
String sql = "select * from user where username = ?";
// 獲取預處理 statement
preparedStatement = connection.prepareStatement(sql);

// 設置參數,第一個參數爲 sql 語句中參數的序號(從 1 開始),第二個參數爲設置的
preparedStatement.setString(1, "王五");
// 向數據庫發出 sql 執行查詢,查詢出結果集
resultSet = preparedStatement.executeQuery();
// 遍歷查詢結果集
while (resultSet.next()) {
System.out.println(
                       resultSet.getString("id")
                       + " " +
                        resultSet.getString("username")
              );
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 釋放資源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block e.printStackTrace();
}
}
}
}
}

 

2.3 Mybatis如何解決JDBC代碼中存在的問題(掌握)

  1. 建立數據庫鏈接相關操做,存在硬編碼

    • 解決方案:經過Mybatis全局配置文件,對數據庫鏈接進行配置

  2. statement相關操做,存在硬編碼

    • 解決方案:經過Mapper映射文件,對statement相關處理進行配置。

  3. 頻繁開啓數據庫鏈接,會下降數據庫處理性能。

    • 解決方案:經過Mybatis全局配置文件,配置鏈接池

2.4 Mybatis工做原理(重點)

  • 咱們要找出的答案就是:從XML配置文件到數據庫的距離有多長?

     

  • 說明

    1. mybatis配置文件

      • SqlMapConfig.xml,此文件做爲mybatis的全局配置文件,配置了mybatis的運行環境等信息。

      • Mapper.xml,此文件做爲mybatis的sql映射文件,文件中配置了操做數據庫的sql語句。此文件須要在SqlMapConfig.xml中加載。

    2. SqlSessionFactory

      • 經過mybatis環境等配置信息構造SqlSessionFactory,即會話工廠。

    3. SqlSession

      • 經過會話工廠建立sqlSession即會話,程序員經過sqlsession會話接口對數據庫進行增刪改查操做。

    4. Executor執行器

      • mybatis底層自定義了Executor執行器接口來具體操做數據庫,Executor接口有兩個實現,一個是基本執行器(默認)、一個是緩存執行器,sqlsession底層是經過executor接口操做數據庫的。

    5. Mapped Statment

      • 它也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個select\insert\update\delete標籤對應一個Mapped Statement對象,select\insert\update\delete標籤的id便是Mapped statement的id。

      • Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor經過Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對prepared Statement設置參數。

      • Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor經過Mapped Statement在執行sql後將輸出結果映射至java對象中,輸出結果映射過程至關於jdbc編程中對結果的解析處理過程。

2.5 MyBatis 核心組件的生命週期

  • SqlsessionFactoryBuilder:方法級別, 方法執行完直接銷燬

  • SqlsessionFactory:全局範圍(應用級別), 能夠看做是一個鏈接池,只存在一個,使用單例

  • Sqlsession:方法級別,一個操做對應一個Sqlsession

3. MyBatis入門

3.1 需求

  1. 根據用戶id查詢一個學生信息

  2. 根據用戶名稱模糊查詢用戶信息列表

  3. 添加學生

  4. 根據id來更新學員的信息

  5. 根據id來刪除學生

3.2 MyBatis開發框架搭建(重點)

  • 建立maven工程,在pom文件中引入mybatis等jar的依賴

       <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.hwua</groupId>
    <artifactId>HelloMyBatis2019.6.11</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
    </dependency>

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.15</version>
    </dependency>

    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    </dependency>

    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.8.0-beta2</version>
    <scope>test</scope>
    </dependency>
    </dependencies>
    </project>
  • 建立數據庫屬性文件db.properties

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:8888/mybatisdb
    username=root
    password=123456
  • 建立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="db.properties"/><!--加載屬性文件 -->
    <!--配置運行環境  -->
     <environments default="development">
       <environment id="development">
         <!--使用mybatis自帶的jdbc事務管理機制  -->
         <transactionManager type="JDBC"/>
         <!--使用mybatis自帶的鏈接池技術 -->
         <dataSource type="POOLED">
           <property name="driver" value="${driver}"/><!--讀取屬性文件中的key:driver-->
           <property name="url" value="${url}"/>
           <property name="username" value="${username}"/>
           <property name="password" value="${password}"/>
         </dataSource>
       </environment>
     </environments>
     <mappers>
       <mapper resource="StudentMapper.xml"/><!-- 引入映射器文件 -->
     </mappers>
    </configuration>
  • 建立log4j日誌記錄配置文件

    log4j.rootLogger=debug, stdout
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

     

  • 配置映射器文件( 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="test">
    <!--配置sql查詢語句 ,parameterType 設置輸入參數的數據類型, resultType 設置輸出參數的數據類型-->
     <select id="queryStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
       select * from Student where id = #{id}
     </select>
    </mapper>
  • 建立pojo類

    package com.hwua.pojo;

    public class Student {
    private Integer id;
    private String sno;
    private String sname;
    private String ssex;
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public String getSno() {
    return sno;
    }
    public void setSno(String sno) {
    this.sno = sno;
    }
    public String getSname() {
    return sname;
    }
    public void setSname(String sname) {
    this.sname = sname;
    }
    public String getSsex() {
    return ssex;
    }
    public void setSsex(String ssex) {
    this.ssex = ssex;
    }
    @Override
    public String toString() {
    return "Student [id=" + id + ", sno=" + sno + ", sname=" + sname + ", ssex=" + ssex + "]";
    }

    }

 

4.使用SqlSession發送SQL來實現業務需求

4.1 根據用戶id查詢一個學生信息

  • 映射文件

    <?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="test">
    <!--配置sql查詢語句 ,parameterType 設置輸入參數的數據類型, resultType 設置輸出參數的數據類型-->
     <select id="queryStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
       select * from Student where id = #{id}
     </select>
    </mapper>
  • 測試代碼

     
  • 源碼解析:

    • SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));解析主配置文件,把配置文件中的信息保存到Configuration對象,並獲得一個DefaultSqlSessionFactory對象

    • XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());解析mapper文件

    • SqlSession sqlSession = sessionFactory.openSession();獲取運行環境,建立一個Executor對象,並返回DefaultSqlSession對象

    • 當執行selectOne方法的時候其實底層交給SimpleExecutor對象調用query方法來進行處理,

    • 在調用query方法的時候底層會產生一個MapperStatement對象,此對象用來進行封裝sql語句,講封裝好的sql語句交給執行器來進行執行.

    • 執行返回的結果交給ResultHandler來進行封裝成返回結果.

4.2 根據學生名稱模糊查詢學生信息列表

  • 映射文件

     <select  id="queryStudentByNameLike" parameterType="string" resultType="com.hwua.pojo.Student">
        <!-- select * from Student where sname like concat('%',#{name},'%') -->
        <!-- select * from Student where sname like #{name} -->
        select * from Student where sname like '%${value}%'
      </select>
    
  • 測試代碼

    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
    		SqlSession sqlSession = sessionFactory.openSession();
    		/*Student stu =(Student)sqlSession.selectOne("test.queryStudentById", 1);
    		System.out.println(stu);*/
    		List<Student> stuList = sqlSession.selectList("queryStudentByNameLike", "張");
    		System.out.println(stuList);
    
  • #{}和${}區別(重點)

    區別1:

    1. #{} :至關於JDBC SQL語句中的佔位符? (PreparedStatement)

    2. ${} 至關於JDBC SQL語句中的鏈接符合 +(Statement)

    區別2:

    1. #{} : 進行輸入映射的時候,會對參數進行類型解析(若是是String類型,那麼SQL語句會自動加上’’)

    2. ${} :進行輸入映射的時候,將參數原樣輸出到SQL語句中

    區別3:

    1. #{} : 若是進行簡單類型(String、Date、8種基本類型的包裝類)的輸入映射時,#{}中參數名稱能夠任意

    2. ${} 若是進行簡單類型(String、Date、8種基本類型的包裝類)的輸入映射時,${}中參數名稱必須是value

    注意:${} :存在SQL注入問題,使用OR 1=1 關鍵字將查詢條件忽略

  • OGNL

    OGNL是Object Graphic Navigation Language(對象圖導航語言)的縮寫,他是一個開源項目。Struts框架使用OGNL做爲默認的表達式語言。

    Student

    -- name

    -- age

    --teacher

    -- name

    -- age #{student.teacher.age}

4.3 添加用戶

  • 映射文件

    <insert id="saveStudent" parameterType="com.hwua.pojo.Student">
         insert into student values(null,#{sno},#{sname},#{ssex})
      </insert>
    
  • 測試代碼

    SqlSession sqlSession = null;
    		try {
    			SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
    					.build(Resources.getResourceAsStream("mybatis-config.xml"));
    			sqlSession = sessionFactory.openSession();
    			Student stu = new Student();
    			stu.setSname("jack");
    			stu.setSno("no006");
    			stu.setSsex("男");
    			int res = sqlSession.insert("test.saveStudent", stu);
    			sqlSession.commit();// 提交事務
    			System.out.println(res);
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    

4.4 更新用戶

  • 映射文件

    <update id="updateStudent" parameterType="com.hwua.pojo.Student">
         update student set sno=#{sno},sname=#{sname},ssex=#{ssex} where id = #{id}
      </update>
    
  • 測試代碼

    SqlSession sqlSession = null;
    		try {
    			SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
    					.build(Resources.getResourceAsStream("mybatis-config.xml"));
    			sqlSession = sessionFactory.openSession();
    			Student stu = (Student) sqlSession.selectOne("test.queryStudentById", 1);
    			stu.setSname("mary");
    			stu.setSsex("女");
    			int res = sqlSession.update("test.updateStudent", stu);
    			sqlSession.commit();// 提交事務
    			System.out.println(res);
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    

4.5 刪除用戶

  • 映射文件

    <delete id="deleteStudent" parameterType="int">
      	delete from student where id = #{id}
      </delete>
    
  • 測試代碼

    SqlSession sqlSession = null;
    		try {
    		SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
    					.build(Resources.getResourceAsStream("mybatis-config.xml"));
    			sqlSession = sessionFactory.openSession();
    			int res = sqlSession.delete("test.deleteStudent", 6);
    			sqlSession.commit();// 提交事務
    			System.out.println(res);
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    

     

5.使用原始Dao的開發方式來開發Dao層

5.1 dao的接口和實現類和工具類

//接口
public interface StudentDao {
   Student findStudentById(Integer id) throws Exception;
   List<Student> findStudentByName(String name) throws Exception;
   int saveStudent(Student student) throws Exception;
   int updateStudent(Student student) throws Exception;
   int deleteStudent(Integer id) throws Exception;
}

//實現類
public class StudentDaoImpl implements StudentDao {

	@Override
	public Student findStudentById(Integer id) throws Exception {
		Student stu = null;
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			stu = (Student) sqlSession.selectOne("queryStudentById", id);
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return stu;
	}

	@Override
	public List<Student> findStudentByName(String name) throws Exception {
		List<Student> stuList = null;
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			stuList = sqlSession.selectList("queryStudentByNameLike", name);
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return stuList;
	}

	@Override
	public int saveStudent(Student student) throws Exception {
		SqlSession sqlSession = null;
		int res =0;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			res = sqlSession.insert("saveStudent", student);
			sqlSession.commit();
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return res;
	}

	@Override
	public int updateStudent(Student student) throws Exception {
		SqlSession sqlSession = null;
		int res =0;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			res = sqlSession.update("updateStudent", student);
			sqlSession.commit();
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return res;
	}

	@Override
	public int deleteStudent(Integer id) throws Exception {
		SqlSession sqlSession = null;
		int res =0;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			res = sqlSession.delete("deleteStudent", id);
			sqlSession.commit();
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return res;
	}

}

//工具類
public class SqlSessionFactoryUtils {
	private static SqlSessionFactory sessionFactory = null;

	//單例去建立SqlSessionFactory
	private static SqlSessionFactory getInstance() throws Exception {
		if (sessionFactory == null) {
			synchronized (SqlSessionFactoryUtils.class) {
				if (sessionFactory == null) {
					sessionFactory = new SqlSessionFactoryBuilder()
							.build(Resources.getResourceAsStream("mybatis-config.xml"));
				}
			}
		}
		return sessionFactory;
	}

	//獲得SqlSession
	public static SqlSession getSqlSession() throws Exception {
		SqlSessionFactory sqlSessionFactory = getInstance();
		return sqlSessionFactory.openSession();
	}
}

5.2 映射文件

<?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="test">
<!--配置sql查詢語句 ,parameterType 設置輸入參數的數據類型, resultType 設置輸出參數的數據類型-->
  <select  id="queryStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
    select * from Student where id = #{id}
  </select>
  <select  id="queryStudentByNameLike" parameterType="com.hwua.pojo.Student" resultType="com.hwua.pojo.Student">
    <!-- select * from Student where sname like concat('%',#{name},'%') --> 
    <!-- select * from Student where sname like #{name} -->
    select * from Student where sname like '%${value}%'
  </select>
  
  <insert id="saveStudent" parameterType="com.hwua.pojo.Student">
     insert into student values(null,#{sno},#{sname},#{ssex})
  </insert>
  <update id="updateStudent" parameterType="com.hwua.pojo.Student">
     update student set sno=#{sno},sname=#{sname},ssex=#{ssex} where id = #{id}
  </update>
  <delete id="deleteStudent" parameterType="int">
  	delete from student where id = #{id}
  </delete>
  
</mapper>

5.3 測試代碼

package com.hwua.test;

import org.junit.Before;
import org.junit.Test;

import com.hwua.pojo.Student;
import com.hwua.service.StudentService;
import com.hwua.service.impl.StudentServiceImpl;

public class StudentTest {
	private StudentService stuService=null;
	@Before
	public void init() {
		stuService = new StudentServiceImpl();
	}
	@Test
	public void testFindStudentById() {
		try {
			Student stu = stuService.findStudentById(1);
			System.out.println(stu);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

6.使用Mapper接口發送SQL(重點)

6.1 XML實現映射器

  • 使用:只須要開發Mapper接口(dao接口)和Mapper約束文件,不須要編寫實現類。

  • 開發規範: Mapper接口開發須要遵循如下規範:

    • Mapper接口的類路徑與Mapper.xml文件中的namespace相同。

    • Mapper接口方法名稱和Mapper.xml中定義的每一個statement的id相同。

    • Mapper接口方法的輸入參數類型和mapper.xml中定義的每一個sql 的parameterType的類型相同。

    • Mapper接口方法的返回值類型和mapper.xml中定義的每一個sql的resultType的類型相同。

  • mapper接口

    package com.hwua.mapper;
    import java.util.List;
    import com.hwua.pojo.Student;
    public interface StudentMapper {
       Student findStudentById(Integer id) throws Exception;
       List<Student> findStudentByName(String name) throws Exception;
       int saveStudent(Student student) throws Exception;
       int updateStudent(Student student) throws Exception;
       int deleteStudent(Integer id) throws Exception;
    }
    
    
  • 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.hwua.mapper.StudentMapper">
    <!--配置sql查詢語句 ,parameterType 設置輸入參數的數據類型, resultType 設置輸出參數的數據類型-->
      <select  id="findStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
        select * from Student where id = #{id}
      </select>
      <select  id="findStudentByName" parameterType="string" resultType="com.hwua.pojo.Student">
        <!-- select * from Student where sname like concat('%',#{name},'%') --> 
        <!-- select * from Student where sname like #{name} -->
        select * from Student where sname like '%${value}%'
      </select>
      
      <insert id="saveStudent" parameterType="com.hwua.pojo.Student">
         insert into student values(null,#{sno},#{sname},#{ssex})
      </insert>
      <update id="updateStudent" parameterType="com.hwua.pojo.Student">
         update student set sno=#{sno},sname=#{sname},ssex=#{ssex} where id = #{id}
      </update>
      <delete id="deleteStudent" parameterType="int">
      	delete from student where id = #{id}
      </delete>
      
    </mapper>
    
  • 主配置文件加載映射文件

    <?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"/><!--加載屬性文件 -->
    <!--配置運行環境  -->
      <environments default="development">
        <environment id="development">
          <!--使用mybatis自帶的jdbc事務管理機制  -->
          <transactionManager type="JDBC"/>
          <!--使用mybatis自帶的鏈接池技術 -->
          <dataSource type="POOLED">
            <property name="driver" value="${driver}"/><!--讀取屬性文件中的key:driver-->
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
     
      <mappers>
        <mapper resource="com/hwua/mapper/StudentMapper.xml"/><!-- 引入映射器文件 -->
      </mappers>
    </configuration>
    
  • 測試代碼

    package com.hwua.mapper;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.hwua.pojo.Student;
    import com.hwua.utils.SqlSessionFactoryUtils;
    
    public class StudentMapperTest {
    	@Test
    	public void testFindStudentById() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一個代理類對象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			Student stu = mapper.findStudentById(1);
    			System.out.println(stu);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    	
    	@Test
    	public void testSaveStudent() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一個代理類對象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			Student stu = new Student();
    			stu.setSname("frank");
    			stu.setSno("no006");
    			stu.setSsex("男");
    			int res=mapper.saveStudent(stu);
    			sqlSession.commit();
    			System.out.println(res);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    	
    	@Test
    	public void testUpdateStudent() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一個代理類對象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			Student stu = mapper.findStudentById(1);
    			stu.setSname("jackson");
    			stu.setSsex("男");
    			int res=mapper.updateStudent(stu);
    			sqlSession.commit();
    			System.out.println(res);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    	
    	@Test
    	public void testDeleteStudent() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一個代理類對象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			int res=mapper.deleteStudent(7);
    			sqlSession.commit();
    			System.out.println(res);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    
    }
    

6.2註解實現映射器(後續講解)

7.全局配置文件

7.1 配置內容

主配置文件中的內容和順序以下:

  屬性
settings 全局配置參數
typeAliases 類型別名
typeHandlers 類型處理器,javaType<--->jdbcType類型之間的轉換
objectFactory 對象工廠
plugins 能夠在Mybatis執行SQL語句的流程中,橫叉一腳去實現一些功能加強,好比PageHelper分頁插件,就是第三方實現的一個插件
environments 環境集合屬性對象,environment(環境子屬性對象),transactionManager(事務管理),dataSource(數據源)
mappers 映射器
databaseIdProvider 數據庫廠商標識

7.2 properties 標籤(重點)

主配置文件能夠引用java屬性文件中的配置信息

  1. 在classpath下定義db.properties文件

     
  2. 在主配置文件中,引用db.properties中的屬性,具體以下:

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:8888/msgdb
    username=root
    password=123456
    
  3. properties標籤除了可使用resource屬性,引用properties文件中的屬性。還能夠在properties標籤內定義property子標籤來定義屬性和屬性值,具體以下:

    <properties resource="db.properties">
        <property name="driver" value="com.mysql.cj.jdbc.Driver1"/>
     </properties>
    

注意:MyBatis 將按照下面的順序來加載屬性:

  • 讀取properties 元素體內定義的屬性。

  • 讀取properties 元素中resource或 url 加載的屬性,它會覆蓋已讀取的同名屬性。

7.3 類型別名(typeAliases)

別名的做用:類型別名是爲 Java 類型設置一個短的名字。 它只和 XML 配置有關,存在的意義僅在於用來減小類徹底限定名的冗餘。

  • 默認類型別名

別名 映射的類型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator
  • 自定義別名

    • 單個別名定義

      <typeAliases>
        <typeAlias alias="user" type="com.hwua.entity.User"/>
      <typeAlias alias="message" type="com.hwua.entity.Message"/>
      </typeAliases>
      
    • 別名包掃描(重點)

      <typeAliases>
        <!-- 包掃描,把包中的類都自動區別名,名別的名字默認是小寫的類名 -->
        <package name="com.hwua.entity"/>
       </typeAliases>
      
    • 當包掃描中一個別名對應多個同名類的時候,會產生衝突,存在二義性,報錯,咱們能夠經過註解來給類指定對應的別名來解決這個問題.

      @Alias("user2")
      public class User {
      	private Integer id;
      	private String name;
      	private String pwd;
      	private String email;
      

       

    • 注意:別名是不區分大小寫的

7.4 映射器(mappers)

既然 MyBatis 的行爲已經由上述元素配置完了,咱們如今就要定義 SQL 映射語句了。 可是首先咱們須要告訴 MyBatis 到哪裏去找到這些語句。 Java 在自動查找這方面沒有提供一個很好的方法,因此最佳的方式是告訴 MyBatis 到哪裏去找映射文件。 你可使用相對於類路徑的資源引用, 或徹底限定資源定位符(包括 file:/// 的 URL),或類名和包名等。例如:

  • 使用相對於類路徑的資源引用

    <!-- 使用相對於類路徑的資源引用 -->
    <mappers>
      <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
      <mapper resource="org/mybatis/builder/PostMapper.xml"/>
    </mappers>
    
  • 使用徹底限定資源定位符(URL)

    <!-- 使用徹底限定資源定位符(URL) -->
    <mappers>
      <mapper url="file:///var/mappers/AuthorMapper.xml"/>
      <mapper url="file:///var/mappers/BlogMapper.xml"/>
      <mapper url="file:///var/mappers/PostMapper.xml"/>
    </mappers>
    
  • 使用映射器接口實現類的徹底限定類名

    <!-- 使用映射器接口實現類的徹底限定類名 -->
    <mappers>
      <mapper class="org.mybatis.builder.AuthorMapper"/>
      <mapper class="org.mybatis.builder.BlogMapper"/>
      <mapper class="org.mybatis.builder.PostMapper"/>
    </mappers>
    
  • 將包內的映射器接口實現所有註冊爲映射器(重點)

    <!-- 將包內的映射器接口實現所有註冊爲映射器 -->
    <mappers>
      <package name="org.mybatis.builder"/>
    </mappers>
    

注意:第三第四種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。

 

8.輸入映射和輸出映射

8.1 輸入參數映射(parameterType)

parameterType屬性能夠映射的輸入參數類型有:簡單類型、POJO類型、Map類型、List類型(動態sql中講)。

  • 輸入多個參數的解決方法, 不要指定parameterType屬性

    • 使用#{arg下標}直接取指定下標所對應參數的值,下標從0開始,可讀性差

      <mapper namespace="com.hwua.mapper.MessageMapper">
        <select id="queryMsgByLimit" resultType="com.hwua.entity.Message" parameterType="com.hwua.entity.User">
           select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{arg0} order by msg_create_date desc limit #{arg1},#{arg2}
        </select>
      </mapper>
      

       

    • 使用#{param下標}直接取指定下標所對應參數的值,下標從1開始,可讀性差

      <mapper namespace="com.hwua.mapper.MessageMapper">
        <select id="queryMsgByLimit" resultType="com.hwua.entity.Message" parameterType="com.hwua.entity.User">
           select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{param1} order by msg_create_date desc limit #{param2},#{param3}
        </select>
      </mapper>
      

       

    • 使用註解@param(" 參數名字")來指定sql語句中的佔位符名字,可讀性比較好,推薦使用(重點)

      public List<Message> queryMsgByLimit(@Param("receiveid")int receiveid,@Param("start")int start,@Param("pageSize")int pageSize) throws SQLException;
      
      <mapper namespace="com.hwua.mapper.MessageMapper">
        <select id="queryMsgByLimit" resultType="com.hwua.entity.Message" parameterType="com.hwua.entity.User">
           select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{receiveid} order by msg_create_date desc limit #{start},#{pageSize}
        </select>
      </mapper>
      
  • 入參使用map來實現多參數的傳遞

    public List<Message> queryMsg(Map<String, Object> map)throws SQLException;
    
     <select id="queryMsg" resultType="com.hwua.entity.Message" parameterType="map">
         <!--#{start} 是傳入map對象中key的名字  -->
         select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{receiveid} order by msg_create_date desc limit #{start},#{pageSize}
      </select>
    

     

8.2 輸出類型映射(resultType)

resultType屬性能夠映射的java類型有:簡單類型、POJO類型、Map類型。

resultType結果爲map類型:就是把一條記錄封裝成一個map對象.map的key指的是表的字段名,值就是表字段所對應的值(瞭解)

public Map<String,Object> findUserById(@Param("id")Integer id)throws SQLException;
public List<Map<String,Object>> findAllUsers()throws SQLException;

 <select id="findUserById" resultType="map" parameterType="int">
     select id,name,pwd,email from users where id=#{id}
  </select>
  
  <select id="findAllUsers" resultType="map">
     select id,name,pwd,email from users
  </select>

 

  • 注意:使用resultType進行輸出映射時,要求sql語句中查詢的列名和要映射的pojo的屬性名一致。

  • 當sql語句中查詢的列名和要映射的pojo的屬性名不一致的時候如何完成映射?

    • 就是在查詢字段的時候,給字段名取一個別名,讓別名和pojo類中的屬性名一致,會完成自動映射

       <select id="querUserById" resultType="user2" parameterType="int">
           select id,name as username,pwd,email from users where id = #{id}
        </select>
      

       

    • 使用resultMap來完成手動映射(就是人爲的去指定記錄中哪一個字段去映射pojo類中的哪一個屬性)

8.3 輸出類型映射(resultMap)(重點)

若是sql查詢列名和pojo的屬性名不一致,能夠經過resultMap將列名和屬性名做一個對應關係,最終將查詢結果映射到指定的pojo對象中。resultType底層也是經過resultMap完成映射的

<select id="querUserById" resultMap="userMapper"
		parameterType="int">
		select id,name,pwd,email from users where id = #{id}
	</select>
	<!--結果映射 type:要映射成哪一個類型的對象 -->
	<resultMap type="user2" id="userMapper">
		<!--對錶中的主鍵進行映射 -->
		<id property="id" column="id" />
		<result property="username" column="name" />
		<result property="pwd" column="pwd" />
		<result property="email" column="email" />
	</resultMap>

 

 

9.關聯查詢(重點)

- 多表查詢,表與表之間存在相應的關係,1對1,1對多,多對對,關聯查詢的數據如何進行映射.關聯查詢是比較複雜的映射,通常使用resultMap來進行復雜映射

9.1 一對一查詢

  • 直接聯表查詢的方式來實現一對一的關係

    <?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.hwua.mapper.TeacherMapper">
    	<select id="findAllTeacher" resultMap="teacherMapper">
    		select t.id
    		tid,t_name,sex,birthday,d.id did,dno,address from teacher t left
    		join
    		driverlicense d on did = d.id
    	</select>
    	<resultMap type="teacher" id="teacherMapper">
    		<id property="id" column="tid" />
    		<result property="t_name" column="t_name" />
    		<result property="sex" column="sex" />
    		<result property="birthday" column="birthday" />
    		<!--配置1對1的關係 -->
    		<association property="driverLicense"
    			javaType="driverLicense">
    			<id property="id" column="did" />
    			<result property="dno" column="dno" />
    			<result property="address" column="address" />
    		</association>
    	</resultMap>
    </mapper>
    
  • 分表查詢的方式來實現1對1的關係(相似於子查詢)

    <!--查詢teacher表中的信息-->
    <select id="findAllTeacher" resultMap="teacherMapper">
    		select id,t_name,sex,birthday,did from teacher
    	</select>
    
    	<resultMap type="teacher" id="teacherMapper">
    		<id property="id" column="id" />
    		<result property="t_name" column="t_name" />
    		<result property="sex" column="sex" />
    		<result property="birthday" column="birthday" />
    		<!--column指的要傳遞個DriverLicense對象中的findDriverLicenseById中的參數  -->
    		<association property="driverLicense" javaType="DriverLicense" column="did"
    		 select="com.hwua.mapper.DriverLicenseMapper.findDriverLicenseById">
    		</association>
    	</resultMap>
    
    public interface TeacherMapper {
    	public List<Teacher> findAllTeacher() throws Exception;
    	public Teacher findTeacherById(Integer id) throws Exception;
    
    }
    	
    <!--查詢駕照表的信息-->
    <mapper namespace="com.hwua.mapper.DriverLicenseMapper">
    	<select id="findDriverLicenseById" parameterType="int"
    		resultType="driverLicense">
    		select id,dno,address from driverlicense where id = #{id}
    	</select>
    </mapper>
    
    
    public interface DriverLicenseMapper {
    	//根據id來找到駕照信息
       DriverLicense findDriverLicenseById(Integer id) throws Exception;
    }
    
    

     

9.2 一對多查詢

  • 第一種方式:多表查詢實現

    <select id="findAllTeacher2" resultMap="teacherMapper2">
    		select t.id,t_name,sex,birthday,d.id did ,dno,address,c.id cid,cno,cname from teacher t left join driverlicense d on t.did = d.id left JOIN course c on t.id = c.tid
    	</select>
    	<resultMap type="teacher" id="teacherMapper2">
    		<id property="id" column="id" />
    		<result property="t_name" column="t_name" />
    		<result property="sex" column="sex" />
    		<result property="birthday" column="birthday" />
    		<association property="driverLicense" javaType="driverLicense">
    		  <id property="id" column="did"/>
    		  <result property="dno" column="dno" />
    		  <result property="address" column="address" />
    		</association>
    		<collection property="cList" javaType="list" ofType="course">
    		  <id property="id" column="cid"/>
    		  <result property="cno" column="cno" />
    		  <result property="cname" column="cname" />
    		</collection>
    	</resultMap>
    
  • 分表查詢

    <!--配置一對多的關係  -->
    <collection property="cList" javaType="list" ofType="course" column="id"
    		select="com.hwua.mapper.CourseMapper.findCoursesById">
    </collection>
    
    <?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.hwua.mapper.CourseMapper">
    	<select id="findCoursesById" parameterType="int"
    		resultType="course">
    		select id,cno,cname from course where tid=#{id}
    	</select>
    </mapper>
    
    public interface CourseMapper {
    	public List<Course> findCoursesById(Integer id);
    }
    

     

9.3 多對多查詢(不支持多對多)

10.延遲加載(重點)

  • 什麼是延遲加載?

    • 就是當用到對象中的數據的時候,才把這個數據庫從數據庫中查找出來.

  • 設置延遲加載,在主配置文件中去開啓延遲加載

    <!--全局配置  -->
    	<settings>
    	   <setting name="lazyLoadingEnabled" value="true"/><!--開啓延遲加載  -->
    	   <setting name="aggressiveLazyLoading" value="true"/><!--開啓層級加載  -->
    	</settings>
    	
    咱們能夠在配置文件中設置fetchType 來覆蓋全局配置文件中的lazyLoadingEnabled的設置
    <!--配置一對多的關係  -->
    <collection property="cList" javaType="list" ofType="course" column="id"
    	select="com.hwua.mapper.CourseMapper.findCoursesById" fetchType="lazy">
    </collection>
    

11.自定義類型轉換器

需求:(須要,把int 轉成 varchar,把1轉換成男存入數據庫,把2轉換女存入數據庫,其它狀況把不肯定存入數據庫)

  1. 建立一個類去繼承BaseHandler,並實現其中的抽象方法

    package com.hwua.typehandler;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.apache.ibatis.type.BaseTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    
    public class IntegerTypeHandler extends BaseTypeHandler<Integer> {
    
    	// javaType--->JdbcType
    	@Override
    	public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
    			throws SQLException {
    
    		if (parameter == 1) {
    			ps.setString(i, "男");
    		} else if (parameter == 2) {
    			ps.setString(i, "女");
    		} else {
    			ps.setString(i, "不肯定");
    		}
    	}
    
    	@Override
    	public Integer getNullableResult(ResultSet rs, String columnName) throws SQLException {
    		String res = rs.getString(columnName);
    		if(res.equals("男")) {
    			return 1;
    		}else if(res.equals("女")) {
    			return 2;
    		}else {
    			return 3;
    		}
    	}
    
    	@Override
    	public Integer getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    		String res = rs.getString(columnIndex);
    		if(res.equals("男")) {
    			return 1;
    		}else if(res.equals("女")) {
    			return 2;
    		}else {
    			return 3;
    		}
    	}
    
    	@Override
    	public Integer getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    		String res = cs.getString(columnIndex);
    		if(res.equals("男")) {
    			return 1;
    		}else if(res.equals("女")) {
    			return 2;
    		}else {
    			return 3;
    		}
    	}
    
    }
    
    
  2. 在全局配置文件中註冊自定義的類型轉換器到環境中

    <!--配置自定義類型轉換器  -->
    <typeHandlers>
    	   <typeHandler handler="com.hwua.typehandler.IntegerTypeHandler" javaType="int" jdbcType="VARCHAR"/>
    </typeHandlers>
    
  3. 使用自定義類型轉換器來進行轉換

    <!--第一種使用方式:指定typeHandler-->
    <mapper namespace="com.hwua.mapper.UserMapper">
    	<select id="findAllUsers" resultMap="userMapper">
    	  select id,name,sex from user
    	</select>
    	
    	<resultMap type="user" id="userMapper">
    	  <id property="id" column="id"/>
    	  <result property="name" column="name"/>
    	  <result property="sex" column="sex" typeHandler="com.hwua.typehandler.IntegerTypeHandler"/>
    	</resultMap>
    	<insert id="saveUser" parameterType="user">
    	  insert into user values(null,#{name},#{sex,typeHandler=com.hwua.typehandler.IntegerTypeHandler})
    	</insert>
    </mapper>
    
    
    <!--第二種使用方式:指定javaType和jdbcType-->
    <?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.hwua.mapper.UserMapper">
    	<select id="findAllUsers" resultMap="userMapper">
    	  select id,name,sex from user
    	</select>
    	
    	<resultMap type="user" id="userMapper">
    	  <id property="id" column="id"/>
    	  <result property="name" column="name"/>
    	  <result property="sex" column="sex" javaType="int" jdbcType="VARCHAR"/>
    	</resultMap>
    	<insert id="saveUser" parameterType="user">
    	  insert into user values(null,#{name},#{sex,javaType=int,jdbcType=VARCHAR})
    	</insert>
    </mapper>
    

     

12.動態SQL(重點)

MyBatis 的強大特性之一即是它的動態 SQL。若是你有使用 JDBC 或其它相似框架的經驗,你就能體會到根據不一樣條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL 這一特性能夠完全擺脫這種痛苦。

12.1 if

<select id="findUser" resultMap="userMapper"
		parameterType="user">
		select id,name,sex from user where 1=1
		<if test="id!=null">
			and id = #{id}
		</if>
		<if test="name!=null">
			and name = #{name}
		</if>
		<if test="sex!=null">
			and sex = #{sex,javaType=int,jdbcType=VARCHAR}
		</if>
	</select>

 

12.2 choose(when,otherwise)

  • 相似於java中的多重if..else if...,也就是多個條件中只會知足一個,當前知足了後面就不會在判斷.

    <select id="findUser" resultMap="userMapper"
    		parameterType="user">
    		select id,name,sex from user
    		<where>
    			<choose>
    				<when test="id!=null">
    					and id = #{id}
    				</when>
    				<when test="name!=null">
    					and name = #{name}
    				</when>
    				<otherwise>
    					and sex = #{sex,javaType=int,jdbcType=VARCHAR}
    				</otherwise>
    			</choose>
    		</where>
    	</select>
    

     

12.3 where

  • 添加where 關鍵字,並把僅跟在where後面的and 或者 or刪除

    <select id="findUser" resultMap="userMapper"
    		parameterType="user">
    		select id,name,sex from user
    		<where>
    			<if test="id!=null">
    				and id = #{id}
    			</if>
    			<if test="name!=null">
    				and name = #{name}
    			</if>
    			<if test="sex!=null">
    				and sex = #{sex,javaType=int,jdbcType=VARCHAR}
    			</if>
    		</where>
    	</select>
    

     

12.4 set

  • 用於更新語句,去掉最後一個逗號

    <update id="updateUser" parameterType="user">
    	   update user
    	   <set>
    	     <if test="name!=null">
    	       name=#{name},
    	     </if>
    	     <if test="sex!=null">
    	       sex=#{sex,javaType=int,jdbcType=VARCHAR},
    	     </if>
    	   </set>
    	   where id=#{id}
    	</update>
    

     

12.5 trim

<update id="updateUser" parameterType="user">
		<!-- update user <set> <if test="name!=null"> name=#{name}, </if> <if test="sex!=null"> 
			sex=#{sex,javaType=int,jdbcType=VARCHAR}, </if> </set> where id=#{id} -->

		update user
		<trim prefix="set" suffixOverrides=",">
			<if test="name!=null">
				name=#{name},
			</if>
			<if test="sex!=null">
				sex=#{sex,javaType=int,jdbcType=VARCHAR},
			</if>
		</trim>
		where id=#{id}
	</update>
<select id="findUser" resultMap="userMapper"
		parameterType="user">
		select id,name,sex from user
		<trim prefix="where"  prefixOverrides="and|or">
			<if test="id!=null">
				and id = #{id}
			</if>
			<if test="name!=null">
				and name = #{name}
			</if>
			<if test="sex!=null">
				and sex = #{sex,javaType=int,jdbcType=VARCHAR}
			</if>
		</trim>
	</select>

 

12.6 foreach

public List<User> findUsers(List<Integer> list)throws Exception;

<select id="findUsers" resultMap="userMapper"
		parameterType="list">
		select id,name,sex from user where id in
		<foreach collection="list" item="item" open="(" separator=","
			close=")">
			#{item}
		</foreach>
</select>

12.7 sql片斷

   <!--聲明sql片斷--> 
    <sql id="userfield">
	   id,name,sex 
	</sql>

	<select id="findAllUsers" resultMap="userMapper">
		select 
		 <!--根據id引入指定的sql片斷-->
       <include refid="userfield"></include>
		from user
	</select>

 

13.MyBatis緩存(瞭解)

1. 一級緩存(自己自帶開啓了)

- 緩存的數據保存在SqlSession中,同一個SqlSession執行的相同的查詢時,第一次從數據庫查詢,把查詢的結果保存到sqlSession中,第二次執行相同查詢的時候,直接從緩存中讀取.
- 爲了保證緩存中和數據庫中數據的一致性,因此當sqlsession執行增刪改,提交事務的操做的時候,會清空一級緩存中的數據

2. 二級緩存(默認是關閉的,通常也不推薦使用)--瞭解

  • 二級緩存的數據保存在SqlSessionFactory中,多個SqlSession查詢的語句會共享二級緩存的數據,當其它SqlSession執行增刪改查的時候都會清空二級緩存,放置數據出現髒讀.

14.PageHelper分頁插件(會用)

14.1 使用PageHelper步驟

  1. 下載jar包

    <dependency>
    	<groupId>com.github.pagehelper</groupId>
    	<artifactId>pagehelper</artifactId>
    	<version>5.1.2</version>
    </dependency>
    

     

  2. 配置PageHelper插件

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- config params as the following -->
            <property name="helperDialect" value="mysql"/>
    	</plugin>
    </plugins>
    
  3. 使用PageHelper實現分頁功能

    package com.hwua.entity;
    
    public class Student {
    	private Integer id;
    
    	@Override
    	public String toString() {
    		return "Student [id=" + id + ", sno=" + sno + ", sname=" + sname + ", ssex=" + ssex + "]";
    	}
    
    	public Integer getId() {
    		return id;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public String getSno() {
    		return sno;
    	}
    
    	public void setSno(String sno) {
    		this.sno = sno;
    	}
    
    	public String getSname() {
    		return sname;
    	}
    
    	public void setSname(String sname) {
    		this.sname = sname;
    	}
    
    	public String getSsex() {
    		return ssex;
    	}
    
    	public void setSsex(String ssex) {
    		this.ssex = ssex;
    	}
    
    	private String sno;
    	private String sname;
    	private String ssex;
    
    }
    
    
    package com.hwua.utils;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    public class SqlSessionFactoryUtils {
    	private static SqlSessionFactory sessionFactory = null;
    
    	//單例去建立SqlSessionFactory
    	private static SqlSessionFactory getInstance() throws Exception {
    		if (sessionFactory == null) {
    			synchronized (SqlSessionFactoryUtils.class) {
    				if (sessionFactory == null) {
    					sessionFactory = new SqlSessionFactoryBuilder()
    							.build(Resources.getResourceAsStream("mybatis-config.xml"));
    				}
    			}
    		}
    		return sessionFactory;
    	}
    
    	//獲得SqlSession
    	public static SqlSession getSqlSession() throws Exception {
    		SqlSessionFactory sqlSessionFactory = getInstance();
    		return sqlSessionFactory.openSession();
    	}
    }
    
    
    package com.hwua.mapper;
    import java.util.List;
    import com.hwua.entity.Student;
    public interface StudentMapper {
    	public List<Student> findStudents();//查詢全部的學生信息
    
    }
    
    <?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.hwua.mapper.StudentMapper">
    	<select id="findStudents" resultType="student">
    		select id,sno,sname,ssex from student
    	</select>
    </mapper>
    
    package com.hwua.service;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.hwua.entity.Student;
    import com.hwua.mapper.StudentMapper;
    import com.hwua.utils.SqlSessionFactoryUtils;
    
    public class StudentService {
    	// 第一個參數第幾頁,第二個每頁要顯示的記錄數
      public List<Student> findStudentsByPage(Integer page,Integer pageSize) throws Exception{
    	  SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
    	  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    	  //使用PageHelper的靜態方法來設置分頁參數
    	  PageHelper.startPage(page, pageSize);//這句話必須放在執行業務以前
    	  List<Student> stuList = mapper.findStudents();
    	  PageInfo<Student> pageInfo = new PageInfo<>(stuList);
    	  System.out.println("當前頁:"+pageInfo.getPageNum());//獲得當前頁
    	  System.out.println("總頁數:"+pageInfo.getPages());//獲得總頁數
    	  System.out.println("總記錄數:"+pageInfo.getTotal());//表中的總記錄數
    	  System.out.println("下一頁:"+pageInfo.getNextPage());
    	  System.out.println("上一頁:"+pageInfo.getPrePage());
    	  System.out.println("全部導航頁號:"+pageInfo.getNavigatepageNums());//
    	  System.out.println("導航條上的第一頁:"+pageInfo.getNavigateFirstPage());
    	  System.out.println("導航條上的最後一頁:"+pageInfo.getNavigateLastPage());
    	  List<Student> list = pageInfo.getList();//當前頁所獲得的記錄的集合
    	  return list;
      }
    }
    
    
    package com.hwua.test;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.hwua.entity.Student;
    import com.hwua.service.StudentService;
    import com.hwua.utils.SqlSessionFactoryUtils;
    
    public class StudentTest {
    	@Test
    	public void testFindStudentByPage() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			StudentService stuService = new StudentService();
    			List<Student> stuList = stuService.findStudentsByPage(2, 3);
    			for(Student stu:stuList) {
    				System.out.println(stu);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    }
    

15.註解開發(瞭解)

相關文章
相關標籤/搜索