Mybatis筆記總結

最美的風景是你發表於2021-01-02

MyBatis總結

1.SSM框架介紹(Spring+SpringMVC+MyBatis)
Junit測試、log4j日誌
2.MyBatis框架
1)MyBatis框架介紹(ORM物件關係對映)工作在三層架構持久層
2)MyBatis的第一個程式:student插入資訊
MyBatis的主配置檔案:連線資料庫的四要素
對映檔案:Sql語句
實現類:SqlSessionFactoryBuilder->SqlSessionFactory->SqlSession->執行sql命令
3)配置檔案解析:定義別名、載入屬性檔案、註冊對映檔案、配置多個連線環境、使用日誌、定義工具類
4)單表的增刪改查(CURD)
5)mapper的動態代理實現增刪改查
使用動態代理條件:
介面和對應對映檔案在同一包下、對映檔案的namespace應該是介面的全限定性類名、sqlSession.getMapper(對映檔案對應介面.class)
6)動態SQL標籤
、、、、sql片段
7)關聯關係查詢:1:n、n:1、1:1、n:m、自關聯
多表連線查詢、多表單獨查詢
的用法
8)欄位名和屬性名不一致:起別名、resultMap
9)延遲載入:關聯關係中關聯物件的多表單獨查詢能使用延遲載入策略
直接載入預設的
侵入式延遲載入
深度延遲載入
延遲載入的開關:主配置檔案中
10)快取
一級快取和二級快取(作用範圍都是namespace)
一級快取的生命週期和SQLSession相同
二級快取的生命週期和整個應用的生命週期相同
一級快取預設開啟,無開關設定
二級快取預設關閉,可以設定開啟或關閉
二級快取的全域性開關在主配置檔案中預設為true
對映檔案中可以開啟在該名稱空間的二級快取
在對映檔案中的也可以單獨設定使用不使用二級快取,用useCache
11)MyBatis註解
註解的基本用法:@Insert、@Update、@Delete、@Select
使用動態Sql:@InsertProvider、@UpdateProvider、@DeleteProvider、@SelectProvider
生成動態sql的方法:字串拼接(StringBuffer)、SQL類(匿名內部類)

一、第一個mybatis程式

  1. 在pow檔案中匯入mybatis相關包
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.21</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

2.編寫mybatis核心配置檔案
在這裡插入圖片描述
3.建立bean類

package com.wcc.beans;
public class Student {
    private Integer id;
    private String name;
    private int age;
    private double score;

    public Student() {
    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

4.建立dao介面類

package com.wcc.dao;

import com.wcc.beans.Student;

public interface IStudentDao {
    void insertStudent(Student student);
}

5.建立dao介面實現類

package com.wcc.dao;

import com.wcc.beans.Student;
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 java.io.IOException;
import java.io.InputStream;

/*
* 1.SqlSessionFactoryBuilder
* 2.SqlSessionFactory
* 3.SqlSession
* */
public class StudentDaoImpl implements IStudentDao {
    @Override
    public void insertStudent(Student student) {
        SqlSession session = null;
        try {
            //1.建立SqlSessionFactoryBulider物件
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //2.載入主配置檔案為InputStream型別
            InputStream is = Resources.getResourceAsStream("mybatis.xml");
            //3.由builder建立SqlSessionFactory
            SqlSessionFactory factory = builder.build(is);
            //4.由factory建立SqlSession
            session = factory.openSession();
            //5.執行插入命令
            session.insert("insertStu",student);
            //6.提交
            session.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //7.關閉SqlSession
            if (session != null){
                session.close();
            }
        }
    }
}

6.建立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">
        //namespace為dao介面層的許可權定性介面名
<mapper namespace="com.wcc.dao.IStudentDao">
    //parameterType為POJO的許可權定性類名
    <insert id="insertStu" parameterType="com.wcc.beans.Student">
        insert into student (name,age,score) values (#{name},#{age},#{score})
    </insert>
</mapper>

7.建立測試類
*/

public class MyTest
{
    @Test
    public void test()
    {
        IStudentDao studentDao = new StudentDaoImpl();
        Student student = new Student("小明",20,98.5);
        studentDao.insertStudent(student);
    }
}

二、優化dao介面實現類

1.將sqlSessionFactory定義為單例模式,提前將Sqlsession建立出來。這樣dao的實現類每次增刪改查就不用在建立sqlSession了。

package com.yyf.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;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtil {
    //因為SqlSessionFactory是重量級元件,把它定義為單例的物件
    private static SqlSessionFactory factory = null;
    public static SqlSession getSqlSession() throws IOException {
        if (factory == null){
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
        }
        return factory.openSession();
    }
}

2.新增log2j日誌,便於除錯程式
1)在pow檔案中引入log2j的依賴

  <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.12.1</version>
    </dependency>

2)java目錄下編寫log2j2.xml檔案

```java
<?xml version="1.0" encoding="UTF-8"?>

<configuration status="OFF">
	<appenders>
		<Console name="myConsole" target="SYSTEM_OUT">
			<PatternLayout pattern="[%-5p] %m%n" />
		</Console>
	</appenders>
	
	<loggers>
		<logger name="com.yyf.dao.IStudentDao" level="trace" additivity="false">
			<appender-ref ref="myConsole" />
		</logger>
		<!--<root level="debug">
			<appender-ref ref="myConsole" />
		</root>-->
	</loggers>
</configuration>

3.給主配置檔案mybatis.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>
    <!--載入jdbc屬性檔案-->
    <properties resource="jdbc.properties"/>

    <!--給實體類定義別名-->
    <typeAliases>
        <!--給指定的類定義指定的別名-->
        <!--<typeAlias type="com.yyf.beans.Student" alias="Stu"/>-->
        <!--給指定包下所有的類起別名,預設別名為該類的簡單類名-->
        <package name="com.yyf.beans"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <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>
        <!--<environment id="oracle">
            <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>
        <!--註冊對映檔案-->
        <!--
            resource一般載入的是內部資源對映檔案
        -->
        <!--<mapper resource="com/yyf/dao/mapper.xml"/>-->
        <!--url一般載入專案的外部資源-->
        <!--<mapper url=""/>-->
        <!--
            1.對映檔案和對應的介面在同一個包下
            2.對映檔案的名稱必須和介面的簡單類名相同
            3.對映檔案中namespace的值必須是對應介面的全限定性類名
        -->
        <!--<mapper class="com.yyf.dao.IStudentDao"/>-->
        <!--
            1.對映檔案和對應的介面在同一個包下
            2.對映檔案的名稱必須和介面的簡單類名相同
            3.對映檔案中namespace的值必須是對應介面的全限定性類名
            4.(可以不滿足)使用動態mapper
        -->
        <package name="com.yyf.dao"/>

    </mappers>
</configuration>

4.將sqlSessionFactory定義為單例模式後的dao介面實現類

package com.yyf.dao;

import com.yyf.beans.Student;
import com.yyf.utils.MyBatisUtil;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
/*
* 1.SqlSessionFactoryBuilder
* 2.SqlSessionFactory
* 3.SqlSession
* */
public class StudentDaoImpl implements IStudentDao {
    //插入學生資訊
    @Override
    public void insertStudent(Student student) {
        SqlSession session = null;
        try {
            //1.通過工具類獲取SqlSession物件
            session = MyBatisUtil.getSqlSession();
            //2.執行插入命令
            session.insert("insertStu",student);
            //3.提交
            session.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //4.關閉SqlSession
            if (session != null){
                session.close();
            }
        }
    }

三、使用mapper代理

使用Mapper的動態代理要求:
* 1.sqlSession.getMapper()中的引數為所要代理介面的型別
* 2.對映檔案的namespace屬性值必須為所代理介面的全限定性類名
* 3.對映檔案中的statement的id必須和代理介面中的相應方法名稱相同
1.測試類中直接呼叫sqlSession

package com.yyf;
import static javafx.scene.input.KeyCode.I;
import static org.junit.Assert.assertTrue;
import com.yyf.beans.Student;
import com.yyf.dao.IStudentDao;
import com.yyf.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MyTest
{
    /**
     * 使用Mapper的動態代理要求:
     * 1.sqlSession.getMapper()中的引數為所要代理介面的型別
     * 2.對映檔案的namespace屬性值必須為所代理介面的全限定性類名
     * 3.對映檔案中的statement的id必須和代理介面中的相應方法名稱相同
     */
    SqlSession sqlSession = null;
    IStudentDao studentDao = null;
    @Before
    public void before() throws IOException {
        sqlSession = MyBatisUtil.getSqlSession();
        studentDao = sqlSession.getMapper(IStudentDao.class);
        System.out.print("代理:"+studentDao);
    }

    @After
    public void after(){
        if (sqlSession != null){
            sqlSession.close();
        }
    }
    //學生資訊插入
    @Test
    public void test01()
    {
        Student student = new Student("小明3",20,98.5);
        studentDao.insertStudent(student);
        sqlSession.commit();
        System.out.print("插入後:"+student);
    }
  }

1.1小知識點
使用動態代理查詢時,會根據所需要的結果預設呼叫方法selectList或selectOne方法。
如果返回結果為List,則預設呼叫selectList方法,否則都預設呼叫selectOne方法
如果需要返回map時,需要在對應的方法介面上新增註解@MapKey(value=“對應欄位名”)
dao介面中程式碼

@MapKey(value = "name")
    Map<String,Student> selectAllStudentMap();

對應xml中程式碼

  <select id="selectAllStudentMap" resultType="Student">
        select id,name,age,score from student
    </select>

對應測試類中的程式碼

  //使用動態代理查詢時,會根據需要的返回結果預設呼叫方法selectList或selectOne,
    //如果返回結果為List,則預設呼叫selectList方法,否則都預設呼叫selectOne方法
    //如果需要返回map時,需要在對應的介面方法上新增註解@MapKey(value="")
    //查詢全部學生資訊Map
    @Test
    public void test08()
    {
        Map<String,Student> map = studentDao.selectAllStudentMap();
        System.out.println(map.get("小明"));
    }

1.2小知識點
如果在介面層需要傳入2個或者多個引數時,需要使用@Param()註解
1.3小知識點
總結:#{}中間可以填寫什麼內容
1.傳入引數為物件時,中間寫物件的屬性名
2.傳入引數為一個基本資料型別或String型別,中間寫任意值,就是一個佔位符
3.傳入引數為map,map的key對應的值是基本資料型別,中間寫map的key
4.傳入引數為map,map的key對應的值是物件,中間寫map的key.屬性

List<Student> selectStudentByCondition3(@Param("name") String name,@Param("age") int age);

註解可以和引數名相同也可以不同,#{}這裡填寫Param中矯正的引數名

1.4常用查詢語句

<?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.yyf.dao.IStudentDao">

    <!--
        1.parameterType可以省略,如果不省略就必須寫正確
        2.傳入的引數是一個物件,#{物件的屬性名},預設呼叫物件屬性的get方法
    -->
    <insert id="insertStudent">
        insert into student (name,age,score) values (#{name},#{age},#{score})
    </insert>

    <delete id="deleteStudentById">
        delete from student where id = #{id}
    </delete>

    <update id="updateStudent">
        update student set name=#{name},age=#{age},score=#{score} where id=#{id}
    </update>

    <insert id="insertStudentCatchId">
        insert into student (name,age,score) values (#{name},#{age},#{score})
        <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
            <!--select @@identity-->
            select last_insert_id()
        </selectKey>
    </insert>

    <!--
        resultType或者resultMap是必須的,並不是集合的型別,而是集合中單個元素的型別
    -->
    <select id="selectAllStudent" resultType="Student">
        select id,name,age,score from student
    </select>

    <select id="selectAllStudentMap" resultType="Student">
        select id,name,age,score from student
    </select>

    <select id="selectStudentById" resultType="Student">
        select id,name,age,score from student where id = #{id}
    </select>

    <select id="selectStudentByName" resultType="Student">
        select id,name,age,score from student where name like '%' #{name} '%'
        <!--select id,name,age,score from student where name like concat('%',#{name},'%')-->
        <!--select id,name,age,score from student where name like '%${value}%'-->
    </select>

    <select id="selectStudentByCondition" resultType="Student">
        select id,name,age,score from student
        where name like '%' #{name} '%' and age &lt; #{age}
    </select>

    <select id="selectStudentByCondition2" resultType="Student">
        <!--select id,name,age,score from student
        where age &gt; #{min} and age &lt; #{max}-->
        select id,name,age,score from student
        where age &gt; #{stu1.age} and age &lt; #{stu2.age}
    </select>

    <select id="selectStudentByCondition3" resultType="Student">
        select id,name,age,score from student
        where name like '%' #{name} '%' and age &lt; #{age}
    </select>
    <!--
        總結:#{}中間可以填寫什麼內容
        1.傳入引數為物件時,中間寫物件的屬性名
        2.傳入引數為一個基本資料型別或String型別,中間寫任意值,就是一個佔位符
        3.傳入引數為map,map的key對應的值是基本資料型別,中間寫map的key
        4.傳入引數為map,map的key對應的值是物件,中間寫map的key.屬性
    -->
</mapper>

四、動態sql語句

1.if的使用

 <select id="selectStudentByIf" resultType="Student">
        select id,name,age,score from student where 1=1
        <if test="name != null and name != ''">
            and name like '%' #{name} '%'
        </if>
        <if test="age > 0">
            and age &lt; #{age}
        </if>
    </select>

注意:如果沒有寫1=1 會報錯
2.where的使用

 <select id="selectStudentByWhere" resultType="Student">
        select id,name,age,score from student
        <where>
            <if test="name != null and name != ''">
                name like '%' #{name} '%'
            </if>
            <if test="age > 0">
                and age &lt; #{age}
            </if>
        </where>
    </select>

注意:當where和if搭配時,第一個if標籤不要加and,其他的加and
3.choose when otherwise標籤

 <!--
        如果輸入了name查詢條件,不論age有沒有輸入,都只按照name查詢;
        如果沒有輸入name,只輸入了age,按照age條件查詢;
        如果兩個都沒有輸入,查詢不到任何結果。
    -->
    <select id="selectStudentByChoose" resultType="Student">
        select id,name,age,score from student
        <where>
            <choose>
                <when test="name != null and name != ''">
                    name like '%' #{name} '%'
                </when>
                <when test="age > 0">
                    age &lt; #{age}
                </when>
                <otherwise>
                    1!=1
                </otherwise>
            </choose>
        </where>
    </select>

4.1foreach標籤 傳入array陣列

<select id="selectStudentByForeachArray" resultType="Student">
        select id,name,age,score from student
        <if test="array != null and array.length > 0">
            where id in
            <foreach collection="array" item="id" open="(" close=")" separator=",">
                #{id}
            </foreach>
        </if>
    </select>

4.2foreach標籤 傳入list集合

<select id="selectStudentByForeachList" resultType="Student">
        select id,name,age,score from student
        <if test="list != null and list.size > 0">
            where id in
            <foreach collection="list" item="id" open="(" close=")" separator=",">
                #{id}
            </foreach>
        </if>
    </select>

4.3foreach標籤 傳入list《T》集合

<select id="selectStudentByForeachList2" resultType="Student">
        select id,name,age,score from student
        <if test="list != null and list.size > 0">
            where id in
            <foreach collection="list" item="stu" open="(" close=")" separator=",">
                #{stu.id}
            </foreach>
        </if>
    </select>

5.sql標籤 include標籤 用於替換重複sql語句

<select id="selectStudentByFragment" resultType="Student">
    <include refid="xxx"/>
    <if test="list != null and list.size > 0">
        where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
            #{stu.id}
        </foreach>
    </if>
</select>
<sql id="xxx">
    select id,name,age,score from student
</sql>

6.if+set標籤
修改使用者資訊時有時候不會修改全部,就使用set標籤

<update id="modify" parameterType="User">
update user 
  <set>
      <if test="name!=null">
        name=#{name}
     </if>
     </set>
         where id = #{id}
   </update>

7.if+trim

<update id="modify" parameterType="User">
update user 
  <trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
      <if test="name!=null">
        name=#{name}
     </if>
     </trim>
   </update>

五,關聯關係查詢

1.一對多(多表連線查詢)
1.1實體類的定義(只展示重要部分)

//一方為主查詢,關聯屬性定義在一方
public class Country {
    private Integer cid;
    private String cname;
    //關聯屬性
    private Set<Minister> ministers;
public class Minister {
    private Integer mid;
    private String mname;

1.2.dao介面

public interface ICountryDao {
    Country selectCountryById(int id);
}

1.3.對映檔案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.yyf.dao.ICountryDao">
    <!--多表連結查詢-->
    <resultMap id="countryMap" type="Country">
        <id column="cid" property="cid"/>
        <result column="cname" property="cname"/>
        <collection property="ministers" ofType="Minister">
            <id column="mid" property="mid"/>
            <result column="mname" property="mname"/>
        </collection>
    </resultMap>
    <select id="selectCountryById" resultMap="countryMap">
        select cid,cname,mid,mname from country,minister
        where cid=#{id} and countryId=cid
    </select>
</mapper>

注意:屬性型別為集合型別時 用collection標籤 型別用ofType

<collection property="ministers" ofType="Minister">

屬性型別為普通型別時用association 標籤 型別用javaType

 <association property="ministers" javaType="Minister"> </association>

2.一對多(多表單獨查詢)

<!--多表單獨查詢-->
<select id="selectMinisterByCountryId" resultType="Minister">
    select mid,mname from minister where countryId=#{cid}
</select>
<resultMap id="countryMap" type="Country">
    <id column="cid" property="cid"/>
    <result column="cname" property="cname"/>
    <collection property="ministers"
                ofType="Minister"
                select="selectMinisterByCountryId"
                column="cid">
    </collection>
</resultMap>
<select id="selectCountryById" resultMap="countryMap">
    select cid,cname from country
    where cid=#{id}
</select>

3.多對一(多表連線查詢)
3.1實體類

//一方為主查詢,關聯屬性定義在一方
public class Country {
    private Integer cid;
    private String cname;
//以多方為主查詢,關聯屬性定義在多方
public class Minister {
    private Integer mid;
    private String mname;
    //關聯屬性,多對一關聯屬性是一個物件
    private Country country;

3.2dao介面

public interface IMinisterDao {
    Minister selectMinisterById(int id);
}

3.3對映檔案xml

<resultMap id="ministerMap" type="Minister">
    <id column="mid" property="mid"/>
    <result column="mname" property="mname"/>
    <association property="country" javaType="Country">
        <id column="cid" property="cid"/>
        <result column="cname" property="cname"/>
    </association>
</resultMap>
<select id="selectMinisterById" resultMap="ministerMap">
    select mid,mname,cid,cname from minister,country
    where mid=#{id} and cid =countryId
</select>

4.多對一(多表單獨查詢)

<!--多表單獨查詢-->
<select id="selectCountryById" resultType="Country">
    select cid,cname from country where cid = #{countryId}
</select>
<resultMap id="ministerMap" type="Minister">
    <id column="mid" property="mid"/>
    <result column="mname" property="mname"/>
    <association property="country"
                 javaType="Country"
                 select="selectCountryById"
                 column="countryId"/>
</resultMap>
<select id="selectMinisterById" resultMap="ministerMap">
    select mid,mname,countryId from minister where mid = #{id}
</select>

5.一對一(多表連線查詢)
5.1實體類

public class Husband {
    private Integer hid;
    private String hname;
    //關聯屬性
    private Wife wife;
public class Wife {
    private Integer wid;
    private String wname;

5.2dao介面

public interface IHusbandDao {
    Husband selectHusbandById(int id);
}

5.3對映檔案xml

    <!--1:1多表連線查詢-->
<resultMap id="husbandMap" type="Husband">
    <id column="hid" property="hid"/>
    <result column="hname" property="hname"/>
    <association property="wife" javaType="Wife">
        <id column="wid" property="wid"/>
        <result column="wname" property="wname"/>
    </association>
</resultMap>
<select id="selectHusbandById" resultMap="husbandMap">
    select hid,hname,wid,wname from husband,wife
    where hid = #{id} and wid = wifeId
</select>

6.一對一(多表單獨查詢)

    <!--1:1多表單獨查詢-->
<select id="selectWifeById" resultType="Wife">
    select wid,wname from wife where wid = #{wifeId}
</select>
<resultMap id="husbandMap" type="Husband">
    <id column="hid" property="hid"/>
    <result column="hname" property="hname"/>
    <association property="wife"
                 javaType="Wife"
                 select="selectWifeById"
                 column="wifeId">
    </association>
</resultMap>
<select id="selectHusbandById" resultMap="husbandMap">
    select hid,hname,wifeId from husband
    where hid = #{id}
</select>

6.1一對一共享主鍵連線查詢

  <!--1:1共享主鍵多表連線查詢-->
    <resultMap id="husbandMap" type="Husband">
        <id column="hid" property="hid"/>
        <result column="hname" property="hname"/>
        <association property="wife" javaType="Wife">
            <id column="wid" property="wid"/>
            <result column="wname" property="wname"/>
        </association>
    </resultMap>
    <select id="selectHusbandById" resultMap="husbandMap">
        select hid,hname,wid,wname from husband,wife
        where hid = #{id} and wid = hid
    </select>

6.2一對一共享主鍵單獨查詢

  <!--1:1共享主鍵多表單獨查詢-->
    <select id="selectWifeById" resultType="Wife">
        select wid,wname from wife where wid = #{wifeId}
    </select>
    <resultMap id="husbandMap" type="Husband">
        <id column="hid" property="hid"/>
        <result column="hname" property="hname"/>
        <association property="wife"
                     javaType="Wife"
                     select="selectWifeById"
                     column="hid">
        </association>
    </resultMap>
    <select id="selectHusbandById" resultMap="husbandMap">
        select hid,hname from husband
        where hid = #{id}
    </select>

7.自關聯一對多(多表連線)
7.1.1實體類

//作為一方
public class Newslabel {
    private Integer id;
    private String name;
    //關聯屬性
    private Set<Newslabel> children;

7.1.2dao介面

public interface INewslabelDao {
    Newslabel selectNewslabelById(int id);
}

7.1.3對映檔案xml

<!--自關聯1:n的多表連線查詢,查詢欄目及其子欄目的資訊(不能查到其孫欄目資訊)-->
<resultMap id="newslabelMap" type="Newslabel">
    <id column="ptid" property="id"/>
    <result column="ptname" property="name"/>
    <collection property="children" ofType="Newslabel">
        <id column="cdid" property="id"/>
        <result column="cdname" property="name"/>
    </collection>
</resultMap>
<select id="selectNewslabelById" resultMap="newslabelMap">
    select pt.id ptid,pt.name ptname,cd.id cdid,cd.name cdname
    from newslabel pt,newslabel cd
    where pt.id=#{id} and cd.pid=pt.id
</select>
7.1自關聯一對多(多表單獨)
    <!--自關聯1:n的多表單獨查詢,查詢欄目及其子孫欄目的資訊-->
<select id="selectNewslabelByParent" resultMap="newslabelMap">
    select id,name from newslabel where pid = #{id}
</select>
<resultMap id="newslabelMap" type="Newslabel">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <collection property="children"
                ofType="Newslabel"
                select="selectNewslabelByParent"
                column="id"/>
</resultMap>
<select id="selectNewslabelById" resultMap="newslabelMap">
    select id,name from newslabel
    where id = #{id}
</select>

7.3自關聯一對多(多表單獨查詢欄目的子孫欄目)

<!--自關聯1:n的多表單獨查詢,查詢欄目的子孫欄目的資訊-->
<select id="selectNewslabelByParent" resultMap="newslabelMap">
    select id,name from newslabel where pid = #{id}
</select>
<resultMap id="newslabelMap" type="Newslabel">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <collection property="children"
                ofType="Newslabel"
                select="selectNewslabelByParent"
                column="id"/>
</resultMap>

7.4自關聯一對多(多表單獨查詢欄目及其父輩欄目)

    <!--自關聯1:n的多表單獨查詢,查詢欄目及其父輩欄目的資訊-->
    <resultMap id="newslabelMap" type="Newslabel">
        <id column="id" property="id"/>
    <result column="name" property="name"/>
    <association property="parent"
                 javaType="Newslabel"
                 select="selectNewslabelById"
                 column="pid"/>
</resultMap>
    <select id="selectNewslabelById" resultMap="newslabelMap">
        select id,name,pid from newslabel
        where id = #{id}
    </select>

8.多對多多表連線查詢
8.1實體類

//以student為主查詢
public class Student {
    private Integer sid;
    private String sname;
    //關聯屬性
    private Set<Course> courses;
public class Course {
    private Integer cid;
    private String cname;

8.2dao介面

public interface IStudentDao {
    Student selectStudentById(int id);
}

8.3對映檔案xml


```java
```java
  <!--n:m多表連線查詢-->
    <resultMap id="studentMap" type="Student">
        <id column="sid" property="sid"/>
        <result column="sname" property="sname"/>
        <collection property="courses" ofType="Course">
            <id column="cid" property="cid"/>
            <result column="cname" property="cname"/>
        </collection>
    </resultMap>
    <select id="selectStudentById" resultMap="studentMap">
        select sid,sname,cid,cname from student,course,middle
        where sid = #{id} and studentId = sid and cid = courseId
    </select>

9.多對多的多表單獨查詢

<!--n:m多單獨接查詢-->
<select id="selectCourseById" resultType="Course">
    select cid,cname from course where cid = #{courseId}
</select>
<resultMap id="middleMap" type="Middle">
    <id column="mid" property="mid"/>
    <association property="course"
                 javaType="Course"
                 select="selectCourseById"
                 column="courseId"/>
</resultMap>
<select id="selectMiddleByStudent" resultMap="middleMap">
    select mid,studentId,courseId from middle where studentId = #{sid}
</select>
<resultMap id="studentMap" type="Student">
    <id column="sid" property="sid"/>
    <result column="sname" property="sname"/>
    <collection property="courses"
                ofType="Course"
                select="selectMiddleByStudent"
                column="sid"/>
</resultMap>
<select id="selectStudentById" resultMap="studentMap">
    select sid,sname from student
    where sid = #{id}
</select>

10.n:m多表連線+單獨查詢

  <!--n:m多表連線+單獨查詢-->
    <select id="selectCourseById" resultType="Course">
        select cid,cname from course where cid = #{courseId}
    </select>
    <resultMap id="studentMap" type="Student">
        <id column="sid" property="sid"/>
        <result column="sname" property="sname"/>
        <collection property="courses"
                    ofType="Course"
                    select="selectCourseById"
                    column="courseId"/>
    </resultMap>
    <select id="selectStudentById" resultMap="studentMap">
        select sid,sname,courseId from student,middle
        where sid = #{id} and studentId = sid
    </select>

小知識點
1.如果數劇庫中的欄位名和實體類中的屬性名不一致
解決方案1:使用resultMap進行手動對映

<!--欄位名和屬性名不一致:使用resultMap手動對映-->
<resultMap id="studentMap" type="Student">
    <id column="sid" property="id"/>
    <result column="sname" property="name"/>
</resultMap>
<select id="selectStudentById" resultMap="studentMap">
    select sid,sname from student where sid = #{id}
</select>

解決方案2:給欄位起別名,讓別名和屬性名相同
例:select sid id,sname name from student ( 數劇庫中欄位名為sid,實體類中為id)

   <!--欄位名和屬性名不一致:給欄位起別名,讓別名和屬性名相同-->
    <select id="selectStudentById" resultType="Student">
        select sid id,sname name from student where sid = #{id}
    </select>

六,延遲載入

延遲載入只在多表單獨查詢時起作用
在這裡插入圖片描述
在這裡插入圖片描述
6.1延遲載入策略預設是關閉的,預設為直接載入。

6.1.1當想使用延遲載入時,可以在mybaits主配置檔案中設定settings標籤的lazyLoadingEnabled屬性設定為ture進行開啟,settings標籤放置有順序,需要要在properties標籤後放置。

6.1.2開啟延遲載入後,預設是深度延遲載入,當使用者查詢主表詳情時,關聯表不會被查詢,只有當查詢到關聯表的詳情後關聯表才被查詢。
6.2主配置檔案

<?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>

    <!--載入jdbc屬性檔案-->
    <properties resource="jdbc.properties"/>

    <settings>
        <!--開啟延遲載入的總開關,預設使用的是深度延遲載入策略-->
        <setting name="lazyLoadingEnabled" value="true"/>
//        <!--總開關開啟,該配置才起作用,侵入式延遲載入的開關-->
  //      <setting name="aggressiveLazyLoading" value="true"/>
    </settings>

    <!--給實體類定義別名-->
    <typeAliases>
        <package name="com.yyf.beans"/>
    </typeAliases>

6.3測試類

 @Test
    public void test()
    {
        Country country = countryDao.selectCountryById(2);
        System.out.println("國家的名稱:" + country.getCname());//關聯表沒有被查詢
//        System.out.println("國家對應部長的個數:" + country.getMinisters().size());此時關聯表才被查詢。
    }

6.2.1 如果想使用侵入式延遲載入,在settings中設定aggressiveLazyLoading屬性為true,同時總開關要開著,不然不起作用

<?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>

    <!--載入jdbc屬性檔案-->
    <properties resource="jdbc.properties"/>

    <settings>
        <!--開啟延遲載入的總開關,預設使用的是深度延遲載入策略-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--總開關開啟,該配置才起作用,侵入式延遲載入的開關-->
       <setting name="aggressiveLazyLoading" value="true"/>
    </settings>

    <!--給實體類定義別名-->
    <typeAliases>
        <package name="com.yyf.beans"/>
    </typeAliases>

6.3.1測試類中當查詢到主表的詳情時就會查詢關聯表

 @Test
    public void test()
    {
        Country country = countryDao.selectCountryById(2);
        System.out.println("國家的名稱:" + country.getCname());
    }

七,快取管理

在這裡插入圖片描述
在這裡插入圖片描述

7.1一級快取預設開啟,無法關閉
一級快取中存放的結果不是查詢結果本身,而是一個map
一級快取底層實現是一個Map
key:hashCode + statementId + SQL語句
value:查詢結果本身

7.1.1兩次查詢相同的student的只進行了一次對數劇庫的查詢
7.1.2如果使用不同的方法,即使查詢的是相同的id也會對資料庫進行兩次查詢
7.1.3不管增刪改是否提交,都會清空一級快取

 //證明:一級快取是存在的
    @Test
    public void test01()
    {
        //第一次查詢
        Student student = studentDao.selectStudentById(2);
        System.out.println("第一次查詢:" + student);

        //第二次查詢
        Student student2 = studentDao.selectStudentById(2);
        System.out.println("第二次查詢:" + student2);
        //兩次查詢相同的student的只進行了一次對數劇庫的查詢
    }
    // 證明:一級快取中存放的結果不是查詢結果本身,而是一個map
    // 一級快取底層實現是一個Map
    // key:hashCode + statementId + SQL語句
    // value:查詢結果本身
    @Test
    public void test02()
    {
        //第一次查詢
        Student student = studentDao.selectStudentById(2);
        System.out.println("第一次查詢:" + student);

        //第二次查詢
        Student student2 = studentDao.selectStudentById2(2);
        System.out.println("第二次查詢:" + student2);
        /如果使用不同的方法,即使查詢的是相同的id也會對資料庫進行兩次查詢
    }

    // 證明:增刪改操作重新整理一級快取(清空一級快取)
    @Test
    public void test03()
    {
        //第一次查詢
        Student student = studentDao.selectStudentById(2);
        System.out.println("第一次查詢:" + student);

        // 插入一個物件
        studentDao.insertStudent(new Student());

        //第二次查詢
        Student student2 = studentDao.selectStudentById(2);
        System.out.println("第二次查詢:" + student2);
        //不管增刪改是否提交,都會清空一級快取
    }

7.2二級快取
全域性開關 是預設開啟的,單個mapper.xml是預設關閉的,如果要使用則需要
1)對應查詢的實體類實現 Serializable介面

public class Student implements Serializable {
    private Integer id;
    private String name;
    private int age;
    private double score;
    public Student() {
    }

2)mapper.xml檔案中建立標籤

<mapper namespace="com.yyf.dao.IStudentDao">

    <!--
        在該名稱空間下開啟二級快取,
        size可以設定二級快取的大小,
        eviction可以設定二級快取的逐出策略,
        flushInterval可以設定二級快取的重新整理間隔
    -->
    <cache size="512" eviction="LRU" flushInterval="10000"/>

    <!--
        flushCache設定該操作是否重新整理二級快取
    -->
        <insert id="insertStudent" flushCache="false">
        insert into student (name,age,score) values (#{name},#{age},#{score})
    </insert>

   <!--useCache設定該查詢方法是否使用快取-->
    <select id="selectStudentById" resultType="Student" useCache="false">
        select id,name,age,score from student where id = #{id}
    </select>
 //證明:二級快取是存在的
    @Test
    public void test01() throws IOException {
        // 第一次查詢

        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        studentDao = sqlSession.getMapper(IStudentDao.class);
        Student student = studentDao.selectStudentById2(6);
        System.out.println("第一次查詢:" + student);
        //關閉SqlSession,清空一級快取
        sqlSession.close();

        SqlSession sqlSession2 = MyBatisUtil.getSqlSession();
        studentDao = sqlSession2.getMapper(IStudentDao.class);
        // 第二次查詢
        Student student2 = studentDao.selectStudentById2(6);
        System.out.println("第二次查詢:" + student2);
        sqlSession2.close();

        SqlSession sqlSession3 = MyBatisUtil.getSqlSession();
        studentDao = sqlSession3.getMapper(IStudentDao.class);
        // 第三次查詢
        Student student3 = studentDao.selectStudentById2(6);
        System.out.println("第三次查詢:" + student3);
        sqlSession3.close();
    }

    // 證明:增刪改操作對二級快取的影響
    // 增刪改操作會重新整理(清空)二級快取
    // 1.重新整理二級快取到底執行了那些???
    // 二級快取的底層也是Map
    // key:hashCode + statemengId + SQL語句
    // value:查詢結果
    // 重新整理二級快取實際上是將二級快取中的所有Entry物件的value置為null
    // 並沒有徹底刪除整個Entry物件,即key仍保留
    // 2.到底何時可以到DB執行select查詢?
    // 有兩種情況可以到DB執行查詢
    // 1>Map中根本就不存在要查詢的Entry,即key未找到
    // 2>Map中存在要查詢的key,但value值為null
    // 3.增刪改預設可以影響二級快取,但也可以讓其不影響二級快取
    // 只需要在增刪改的statement中新增屬性flushCache="false"即可

7.3使用第三方二級快取
7.3.1在pow檔案中引入第三方快取所需要的依賴

 <!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
    <dependency>
      <groupId>org.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>3.8.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
    <dependency>
      <groupId>org.mybatis.caches</groupId>
      <artifactId>mybatis-ehcache</artifactId>
      <version>1.2.1</version>
    </dependency>

7.3.2mybatis主配置檔案

<configuration>
    <!--載入jdbc屬性檔案-->
    <properties resource="jdbc.properties"/>
    
    <settings>
        <!--使用log4j2的日誌-->
        <setting name="logImpl" value="LOG4J2"/>
        <!--二級快取的總開關,預設是開啟的-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

7.3.3mapper對映檔案

<mapper namespace="com.yyf.dao.IStudentDao">

    <!--使用DHCache第三方快取,把type型別設定為第三方快取型別-->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache">
        <property name="timeToLiveSeconds" value="1000"/>
    </cache>

    <!--
        flushCache設定該操作是否重新整理二級快取
    -->
    <insert id="insertStudent" flushCache="false">
        insert into student (name,age,score) values (#{name},#{age},#{score})
    </insert>
    <!--useCache設定該查詢方法是否使用快取-->
    <select id="selectStudentById" resultType="Student" useCache="false">
        select id,name,age,score from student where id = #{id}
    </select>

小結:

 1.二級快取可以全域性性關閉
 當前應用中所有查詢均不能使用二級快取,在mybatis的主配置檔案
 2.二級快取可以區域性性關閉
 可以指定在某一個對映檔案中是否使用二級快取,在對映檔案中使用<cache/>
 3.二級快取可以進行對某個查詢方法是否使用二級快取進行設定
 在對應查詢標籤<select>中天健屬性useCahce=“false”即可關閉

八,mybatis註解

package com.yyf.dao;
import com.yyf.beans.Student;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;
public interface IStudentDao {
    // 1.註解是以@開頭,首字母大寫的,因為註解是類層級的成員,類層級的成員:類、介面、註解、列舉
    // 2.對註解中陣列型別的屬性賦值,使用{元素1,元素2,.....}
    // 3.如果陣列型別的屬性只有一個元素,那麼{}可以省略
    // 4.若果註解只使用到了一個屬性,並且屬性名為value,那麼這個value名稱可以省略

    @Insert(value = {"insert into student (name,age,score) values(#{name},#{age},#{score})"})
    void insertStudent(Student student);

    @Delete(value = "delete from student where id = #{xx}")
    void deleteStudentById(int id);

    @Update("update student set name=#{name},age=#{age},score=#{score} where id = #{id}")
    void updateStudent(Student student);
  //當我們向主鍵是自增型的資料庫表中(如 user 表)插入一條記錄時,我們期望獲取剛剛寫入這條記錄
  //的id,(因為某些場景下需要獲得這個id去做其他的操作),此時我們需要使用SELECT LAST_INSERT_ID()
  //這個語句來獲取插入記錄後返回的自增id的值;
    @Insert("insert into student (name,age,score) values(#{name},#{age},#{score})")
    @SelectKey(statement = "select last_insert_id()",keyProperty = "id",before = false,resultType = int.class)
    void insertStudentCatchId(Student student);

    @Select("select id,name,age,score from student")
    List<Student> selectAllStudent();

    @MapKey(value = "name")
    @Select("select id,name,age,score from student")
    Map<String,Student> selectAllStudentMap();

    @Select("select id,name,age,score from student where id = #{xx}")
    Student selectStudentById(int id);

    @Select("select id,name,age,score from student where name like '%' #{name} '%'")
    List<Student> selectStudentByName(String name);

    @Select("select id,name,age,score from student where name like '%' #{name} '%' and age < #{age}")
    List<Student> selectStudentByCondition(Student student);

    //@Select("select id,name,age,score from student where age < #{max} and age > #{min}")
    @Select("select id,name,age,score from student where age < #{stu2.age} and age > #{stu1.age}")
    List<Student> selectStudentByCondition2(Map map);

    @Select("select id,name,age,score from student where name like '%' #{name} '%' and age < #{age}")
    List<Student> selectStudentByCondition3(@Param("name") String name,@Param("age") int age);

}

九,mybatis註解動態sql
9.1dao介面

public interface IStudentDao {

    @InsertProvider(type = MySqlProvider.class, method = "getInsertSql")
    void insertStudent(Student student);

    @DeleteProvider(type = MySqlProvider.class, method = "getDeleteSql")
    void deleteStudentById(int id);

    //@UpdateProvider(type = MySqlProvider.class, method = "getUpdateSql")
    //@UpdateProvider(type = MySqlProvider.class, method = "getUpdateSql2")
    @UpdateProvider(type = MySqlProvider.class, method = "getUpdateSql3")
    void updateStudent(Student student);

    @InsertProvider(type = MySqlProvider.class, method = "getInsertSql")
    @SelectKey(statement = "select last_insert_id()",keyProperty = "id",before = false,resultType = int.class)
    void insertStudentCatchId(Student student);

    @SelectProvider(type = MySqlProvider.class, method = "getSelectSql")
    List<Student> selectAllStudent();

    @SelectProvider(type = MySqlProvider.class, method = "getSelectSql")
    Student selectStudentById(Integer id);

    @SelectProvider(type = MySqlProvider.class, method = "getSelectSql2")
    List<Student> selectStudentByName(String name);

    @MapKey(value = "name")
    @SelectProvider(type = MySqlProvider.class,method = "getSelectSql")
    Map<String,Student> selectAllStudentMap();

    @SelectProvider(type = MySqlProvider.class, method = "getSelectSql3")
    List<Student> selectStudentByCondition(Student student);

    @SelectProvider(type = MySqlProvider.class, method = "getSelectSql4")
    List<Student> selectStudentByCondition2(Map map);

    //@SelectProvider(type = MySqlProvider.class, method = "getSelectSql5")
    @SelectProvider(type = MySqlProvider.class, method = "getSelectSql6")
    List<Student> selectStudentByCondition3(@Param("name") String name,@Param("age") int age);

}

9.2MySqlProvider類

package com.yyf.dao;

import com.yyf.beans.Student;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.SQL;

import java.util.Map;

/**
 * company: www.abc.com
 * Author: Administrator
 * Create Data: 2020/10/26 0026
 */
public class MySqlProvider {
    public String getInsertSql(){
        return "insert into student (name,age,score) values(#{name},#{age},#{score})";
    }

    public String getDeleteSql(){
        return "delete from student where id = #{id}";
    }

    public String getUpdateSql(){
        return "update student set name=#{name},age=#{age},score=#{score} where id = #{id}";
    }

    public String getSelectSql(Integer id){
        if (id != null){
            return "select id,name,age,score from student where id = #{id}";
        }else {
            return "select id,name,age,score from student";
        }
    }
    public String getSelectSql2(){
        return "select id,name,age,score from student where name like '%' #{name} '%'";
    }

    public String getSelectSql3(Student student){
        StringBuffer sql = new StringBuffer();
        sql.append("select id,name,age,score from student where 1=1");
        if (student.getName() != null && !"".equals(student.getName())){
            sql.append(" and name like '%' #{name} '%'");
        }
        if (student.getAge() > 0){
            sql.append(" and age < #{age}");
        }
        return sql.toString();
    }

    public String getSelectSql4(Map map){
        StringBuffer sql = new StringBuffer();
        sql.append("select id,name,age,score from student where 1=1");
        if ((Integer)map.get("min") > 0){
            sql.append(" and age > #{min}");
        }
        if ((Integer)map.get("max") > 0){
            sql.append(" and age < #{max}");
        }
        return sql.toString();
    }

    public String getSelectSql5(@Param("name") String name, @Param("age") int age){
        StringBuffer sql = new StringBuffer();
        sql.append("select id,name,age,score from student where 1=1");
        if (name != null && !"".equals(name)){
            sql.append(" and name like '%' #{name} '%'");
        }
        if (age > 0){
            sql.append(" and age < #{age}");
        }
        return sql.toString();
    }

    public String getSelectSql6(Map map){
        StringBuffer sql = new StringBuffer();
        sql.append("select id,name,age,score from student where 1=1");
        if (map.get("name") != null && !"".equals(map.get("name"))){
            sql.append(" and name like '%' #{name} '%'");
        }
        if ((Integer)map.get("age") > 0){
            sql.append(" and age < #{age}");
        }
        return sql.toString();
    }
    public String getUpdateSql2(Student student){
        StringBuffer sql = new StringBuffer();
        //update student set name=#{name},age=#{age},score=#{score} where id = #{id}
        sql.append("update student set id = #{id}");
        if (student.getName() != null && !"".equals(student.getName())){
            sql.append(",name = #{name}");
        }
        if (student.getAge() > 0){
            sql.append(",age = #{age}");
        }
        if (student.getScore() > 0){
            sql.append(",score = #{score}");
        }
        sql.append(" where id = #{id}");
        return sql.toString();
    }

    public String getUpdateSql3(final Student student){
        // new SQL(){}表示建立一個SQL類的子類的物件,只不過這個子類叫什麼名稱不知道,也沒有指定
        // 所以,這種寫法叫做匿名內部類
        return new SQL(){
            // 下面的程式碼在何時被執行?
            // 噹噹前類(SQL類的子類)的無參構造器被呼叫時,會自動執行這段程式碼
            // 在類中的{}稱為例項程式碼塊
            {
                this.UPDATE("student");
                this.SET("id = #{id}");
                if (student.getName() != null && !"".equals(student.getName())){
                    this.SET("name = #{name}");
                }
                if (student.getAge() > 0){
                    this.SET("age = #{age}");
                }
                if (student.getScore() > 0){
                    this.SET("score = #{score}");
                }
                this.WHERE("id = #{id}");
            }
        }.toString();
    }
}

9.3測試類

public class MyTest
{
    SqlSession sqlSession = null;
    IStudentDao studentDao = null;
    @Before
    public void before() throws IOException {
        sqlSession = MyBatisUtil.getSqlSession();
        studentDao = sqlSession.getMapper(IStudentDao.class);
        //System.out.print("代理:"+studentDao);
    }

    @After
    public void after(){
        if (sqlSession != null){
            sqlSession.close();
        }
    }
    //學生資訊插入
    @Test
    public void test01()
    {
        Student student = new Student("小明3",20,98.5);
        studentDao.insertStudent(student);
        sqlSession.commit();
        System.out.print("插入後:"+student);
    }
    //刪除學生資訊按id
    @Test
    public void test02()
    {
        studentDao.deleteStudentById(18);
        sqlSession.commit();
    }
    //修改學生資訊按id
    @Test
    public void test03()
    {
        Student student = new Student("小綠",0,0);
        student.setId(10);
        studentDao.updateStudent(student);
        sqlSession.commit();
    }
    //獲取最新插入的學生id
    @Test
    public void test04()
    {
        Student student = new Student("小小1",18,88);
        studentDao.insertStudentCatchId(student);
        sqlSession.commit();
        System.out.print("插入後:"+student);
    }
    //查詢全部學生資訊List
    @Test
    public void test05()
    {
        List<Student> students = studentDao.selectAllStudent();
        for (Student s:students){
            System.out.println(s);
        }
    }
    //按照id查詢學生資訊
    @Test
    public void test06()
    {
        Student student = studentDao.selectStudentById(6);
            System.out.println(student);
    }
    //按照name查詢學生資訊
    @Test
    public void test07()
    {
        List<Student> students = studentDao.selectStudentByName("明");
        for (Student s:students){
            System.out.println(s);
        }
    }
    //使用動態代理查詢時,會根據需要的返回結果預設呼叫方法selectList或selectOne,
    //如果返回結果為List,則預設呼叫selectList方法,否則都預設呼叫selectOne方法
    //如果需要返回map時,需要在對應的介面方法上新增註解@MapKey(value="")
    //查詢全部學生資訊Map
    @Test
    public void test08()
    {
        Map<String,Student> map = studentDao.selectAllStudentMap();
        System.out.println(map.get("小明3"));
    }
    //複合條件查詢學生資訊
    @Test
    public void test09()
    {
        //Student student = new Student("明",20,-1);
        //Student student = new Student("明",0,-1);
        //Student student = new Student(null,20,-1);
        Student student = new Student(null,0,-1);
        List<Student> students = studentDao.selectStudentByCondition(student);
        for (Student s:students){
            System.out.println(s);
        }
    }
    //複合條件查詢學生資訊2
    @Test
    public void test10()
    {
        Map map = new HashMap();
        /*Student stu1 = new Student(null,16,-1);
        Student stu2 = new Student(null,20,-1);
        map.put("stu1",stu1);
        map.put("stu2",stu2);*/
        map.put("min",16);
        map.put("max",20);
        List<Student> students = studentDao.selectStudentByCondition2(map);
        for (Student s:students){
            System.out.println(s);
        }
    }

    //複合條件查詢學生資訊3
    @Test
    public void test11()
    {
        List<Student> students = studentDao.selectStudentByCondition3("明",20);
        for (Student s:students){
            System.out.println(s);
        }
    }
 }

完結…

相關文章