MyBatis進階--介面代理方式實現Dao 和動態SQL

星夢淚痕發表於2021-05-23

 

MyBatis介面代理方式實現Dao層

介面代理方式-實現規則

傳統方式實現Dao層,我們既要寫介面。還要寫實現類。而MyBatis框架可以幫助我們省略寫Dao層介面實現類的步驟。程式設計師只需要編寫介面,由MyBatis框架根據介面的定義來創

1該介面的動態代理物件。

實現規則:

  1.對映配置檔案中的名稱空間必須和Dao層介面的全類名相同

  2.對映配置檔案中的增刪改查標籤的id屬性必須和Dao層介面的方法名相同

  3.對映配置檔案中的增刪改查標籤的paramrterType屬性必須和Dao層介面方法的引數相同

  4.對映配置檔案中的增刪改查標籤的resultType屬性必須和Dao層介面方法的返回值相同

介面代理方式-程式碼實現

1.刪除mapper層介面的實現類

2.修改對映配置檔案

3.修改service層介面的實現類,採用介面代理方式實現功能

 

 

 

 刪除mapper層介面的實現類

 

 

 修改對映配置檔案

package com.itheima.service.impl;

import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
import com.itheima.service.StudentService;
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;
/*
    業務層實現類
 */
public class StudentServiceImpl implements StudentService {

    @Override
    public List<Student> selectAll() {
        List<Student> list = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            list = mapper.selectAll();

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return list;
    }

    @Override
    public Student selectById(Integer id) {
        Student stu = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            stu = mapper.selectById(id);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return stu;
    }

    @Override
    public Integer insert(Student stu) {
        Integer result = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            result = mapper.insert(stu);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return result;
    }

    @Override
    public Integer update(Student stu) {
        Integer result = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            result = mapper.update(stu);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return result;
    }

    @Override
    public Integer delete(Integer id) {
        Integer result = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            result = mapper.delete(id);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return result;
    }
}

修改service層介面的實現類,採用介面代理方式實現功能

介面代理方式-原始碼分析

分析動態代理物件如何生成的?

  通過動態代理開發的模式,我們只需要編寫一個介面,不寫實現類,我們通過getMapper()方法最終獲取到

org.apache.ibatis.binding.MapperProxy代理物件,然後執行功能,而這個代理物件正是MyBatis使用了JDK的動態代理技術,幫助我們生成了代理實現類物件。從而可以進行相關持久化操作。

分析方法是如何執行的?

  動態代理的實現類物件再執行方法的時候最終呼叫了maperMethod.execute()方法,這個方法中通過switch語句根據操作型別來判斷是新增,修改,刪除,查詢操作,最後一步回到了MMyBatis最原生的SqlSession方式來執行增刪改查。

介面代理方式小結

介面代理方式可以讓我們只編寫介面即可,而實現類物件由MyBatis生成。

實現規則:

  1.對映配置檔案中的名稱空間必須和Dao層介面的全類名相同

  2.對映配置檔案中的增刪改查標籤的id屬性必須和Dao層介面的方法名相同

  3.對映配置檔案中的增刪改查標籤的paramrterType屬性必須和Dao層介面方法的引數相同

  4.對映配置檔案中的增刪改查標籤的resultType屬性必須和Dao層介面方法的返回值相同

獲取動態代理物件

  SqlSession功能類中的getMapper()方法

刪除mapper中的實現類 ,保留介面

在StudentMapper.xml中修改  <mapper namespace="com.itheima.mapper.StudentMapper">

更改service包下 StudentServiceImpl檔案

package com.itheima.service.impl;

import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
import com.itheima.service.StudentService;
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;
/*
    業務層實現類
 */
public class StudentServiceImpl implements StudentService {

    @Override
    public List<Student> selectAll() {
        List<Student> list = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            list = mapper.selectAll();

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return list;
    }

    @Override
    public Student selectById(Integer id) {
        Student stu = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            stu = mapper.selectById(id);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return stu;
    }

    @Override
    public Integer insert(Student stu) {
        Integer result = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            result = mapper.insert(stu);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return result;
    }

    @Override
    public Integer update(Student stu) {
        Integer result = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            result = mapper.update(stu);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return result;
    }

    @Override
    public Integer delete(Integer id) {
        Integer result = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.載入核心配置檔案
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.獲取SqlSession工廠物件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通過工廠物件獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession(true);

            //4.獲取StudentMapper介面的實現類物件
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通過實現類物件呼叫方法,接收結果
            result = mapper.delete(id);

        } catch (Exception e) {

        } finally {
            //6.釋放資源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回結果
        return result;
    }
}

  建立dynamic下測試類Test01

package com.itheima.dynamic;

import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class Test01 {
    @Test
    public void selectCondition() throws Exception {
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        Student stu=new Student();
        stu.setId(2);
        stu.setName("李四");
        //stu.setAge(23);
        List<Student> list = mapper.selectCondition(stu);

        for (Student student:list){
            System.out.println(student);
        }
        sqlSession.close();
        is.close();
    }
    @Test
    public void selectByIds() throws Exception {
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

       List<Integer> ids=new ArrayList<>();
       ids.add(1);
       ids.add(2);
        List<Student> list = mapper.selectByIds(ids);

        for (Student student:list){
            System.out.println(student);
        }
        sqlSession.close();
        is.close();
    }
}

  

 

 

 

MyBatis對映配置檔案-----動態sql

動態SQL介紹

  MyBatis對映配置檔案中,前面我們的SQL都是比較簡單的,有些時候業務邏輯複雜時,我們的SQL就時動態變化的,此時在前面學習的SQL就不能滿足要求了。

  多條件查詢

  id:3               name:王五           age:25

 select * from Student where id=#{id} and name=#{name} and age=#{age}

  id:3               name:王五

 select * from Student where id=#{id} and name=#{name}

  動態sql標籤

<where>:條件標籤。如果有動態條件,則使用該標籤代替where關鍵字。

<if>:條件判斷標籤

    

<if test="條件判斷">

    查詢條件拼接
</if>

<foreach>:迴圈遍歷標籤。適用於多個引數或者的關係。

<foreach collection="" open="" close="" item="" separator="">
    獲取引數
</foreach>

 屬性:

  collection:引數容器型別,(list-集合,array-陣列)。

  open:開始的sql語句

  close:結束額sql語句

  item:引數變數名

  separator:分隔符

Sql片段抽取

我們可以將一些重複的SQL語句進行抽取,以達到複用的效果

<sql>:  抽取SQL語句標籤

<sql id ="片段唯一標識" >抽取的SQL語句</sql>

<include>:引入SQL片段標籤

<include refid="片段唯一標識" />

 

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD約束-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    mapper:核心根標籤
    namespace屬性:名稱空間


-->
<mapper namespace="com.itheima.mapper.StudentMapper">
    <sql id="select">Select * FROM Student</sql>
    <!--
        select:查詢功能的標籤
        id屬性:唯一標識
        resultType屬性:指定結果對映物件的型別
        parameterType:指定引數對映物件型別
    -->
    <select id="selectAll" resultType="student">
        <include refid="select"/>
    </select>
    
    <select id="selectById" resultType="student" parameterType="int">
        <include refid="select"/> where id = #{id}
    </select>

    <insert id="insert" parameterType="student">
        Insert into Student values(#{id},#{name},#{age})
    </insert>

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

    <delete id="delete" parameterType="int">
        delete from Student where id=#{id}
    </delete>
    <select id="selectCondition" resultType="student" parameterType="student">
        <include refid="select"/>
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="name!=null">
                and name=#{name}
            </if>
            <if test="age!=null">
                and age=#{age}
            </if>
        </where>
    </select>

    <select id="selectByIds" resultType="student" parameterType="list">
        <include refid="select"/>
        <where>
            <foreach collection="list" open="id in (" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
    </select>

</mapper>

  動態SQL小結

動態SQL指的就是SQL語句可以根據條件或者引數的不同進行動態的變化

<where>:條件標籤

<if>:裡面有個test標籤可以幫我們進行判斷

<foreach>:迴圈遍歷的標籤  collection="list" open="id in (" close=")" item="id" separator=","

<sql>:抽取SQL片段的標籤

<include>:引入SQL片段的標籤

 

相關文章