動力節點—2020最新MyBatis教程筆記



本文為動力節點2020MyBatis筆記整理,視頻地址為https://www.bilibili.com/video/BV185411s7Ry?from=search&seid=5830402177484068371。
王鶴老師的筆記可自行去動力節點官網下載。

1 介紹

Java WEB 通常分為三層,即表示層,業務邏輯層,數據訪問層。

三層的職責

  1. 界面層(表示層,視圖層):主要功能是接受用戶的數據,顯示請求的處理結果。使用 web 頁面和用戶交互,手機 app 也就是表示層的,用戶在 app 中操作,業務邏輯在服務器端處理。

  2. 業務邏輯層:接收表示傳遞過來的數據,檢查數據,計算業務邏輯,調用數據訪問層獲取數據。

  3. 數據訪問層:與數據庫打交道。主要實現對數據的增、刪、改、查。將存儲在數據庫中的數據提交給業務層,同時將業務層處理的數據保存到數據庫

具體過程為:用戶---> 界面層(Spring MVC)--->業務邏輯層(Spring)--->數據訪問層(MyBatis)--->DB 數據庫。

MyBatis 框架:

MyBatis 是一個優秀的基於 java 的持久層框架,內部封裝了 jdbc,開發者只需要關注 sql 語句本身,而不需要處理加載驅動、創建連接、創建 statement、關閉連接,資源等繁雜的過程。

MyBatis 通過 xml 或注解兩種方式將要執行的各種 sql 語句配置起來,並通過 java 對象和 sql 的動態參數進行映射生成最終執行的 sql 語句,最后由 mybatis 框架執行 sql 並將結果映射為 java 對象並返回。

2 快速入門

對於MyBatis項目來說,除了maven本身的pom.xml以外,還有主配置文件mybatis-config.xml,通常放在Resource目錄下;以及各個Dao接口對應的在同級目錄下且同名的xml映射文件。在主配置文件中,可以設置數據源,事務,別名,日志,分頁以及映射器位置,在Dao對應的映射文件中,通常是寫相應的SQL語句來實現Dao的各種功能。

2.1 操作步驟(P9)

2.1.1 首先創建maven

(1)創建maven:New Project/Module->選擇Maven,打鈎Create from archetype,選擇 :maven-archetype-quickstart,next->輸入Name/Location,點開Artifact Coordinates,輸入相應Id。

(2)等待加載完成后,在src/main上右擊,產生resources目錄,resources下面的資源在編譯后在target/classes下面。

2.1.2 接着會做一些配置

(1)在pom.xml中,修改properties中的1.7為1.8,刪除maven原有的build,加入maven的依賴,包括mybatis和mysql驅動,以及一個掃描src/main/java目錄下的各種資源放入編譯后的target下的classes

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.9</version>
  </dependency>
</dependencies>


<build>
  <resources>
    <resource>
      <directory>src/main/java</directory><!--所在的目錄-->
      <includes><!--包括目錄下的.properties,.xml 文件都會掃描到-->
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>false</filtering>
    </resource>
  </resources>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>

(2)創建Dao接口以及涉及到的Bean對象

(3)創建mapper文件,也叫sql映射文件,是一個xml:寫sql語句的,和接口中方法對應的sql語句。

<?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.bjpowernode.dao.StudentDao">
    <!--
       select:表示查詢操作。
       id: 你要執行的sql語法的唯一標識, mybatis會使用這個id的值來找到要執行的sql語句
           可以自定義,但是要求你使用接口中的方法名稱。

       resultType:表示結果類型的, 是sql語句執行后得到ResultSet,遍歷這個ResultSet得到java對象的類型。
          值寫的類型的全限定名稱
    -->

    <select id="selectStudents" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student order by id
    </select>


    <!--插入操作-->
    <insert id="insertStudent">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
</mapper>
<!--
  sql映射文件(sql mapper): 寫sql語句的, mybatis會執行這些sql
  1.指定約束文件
     <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    mybatis-3-mapper.dtd是約束文件的名稱, 擴展名是dtd的。
  2.約束文件作用:  限制,檢查在當前文件中出現的標簽,屬性必須符合mybatis的要求。

  3.mapper 是當前文件的根標簽,必須的。
    namespace:叫做命名空間,唯一值的, 可以是自定義的字符串。
               要求你使用dao接口的全限定名稱。

  4.在當前文件中,可以使用特定的標簽,表示數據庫的特定操作。
   <select>:表示執行查詢,select語句
   <update>:表示更新數據庫的操作, 就是在<update>標簽中 寫的是update sql語句
   <insert>:表示插入, 放的是insert語句
   <delete>:表示刪除, 執行的delete語句
-->

(4)創建mybatis的一個主配置文件,也是xml,放在resources下,1)連接數據庫;2)指定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>

    <!--settings:控制mybatis全局行為-->
    <settings>
        <!--設置mybatis輸出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <!--環境配置: 數據庫的連接信息
        default:必須和某個environment的id值一樣。
        告訴mybatis使用哪個數據庫的連接信息。也就是訪問哪個數據庫
    -->
    <environments default="mydev">
        <!-- environment : 一個數據庫信息的配置, 環境
             id:一個唯一值,自定義,表示環境的名稱。
        -->
        <environment id="mydev">
            <!--
               transactionManager :mybatis的事務類型
                   type: JDBC(表示使用jdbc中的Connection對象的commit,rollback做事務處理)
            -->
            <transactionManager type="JDBC"/>
            <!--
               dataSource:表示數據源,連接數據庫的
                  type:表示數據源的類型, POOLED表示使用連接池
            -->
            <dataSource type="POOLED">
                <!--
                   driver, user, username, password 是固定的,不能自定義。
                -->
                <!--數據庫的驅動類名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--連接數據庫的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
                <!--訪問數據庫的用戶名-->
                <property name="username" value="root"/>
                <!--密碼-->
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一個mapper標簽指定一個文件的位置。
           從類路徑開始的路徑信息。  target/clasess(類路徑)
        -->
        <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
    </mappers>
</configuration>
<!--
   mybatis的主配置文件: 主要定義了數據庫的配置信息, sql映射文件的位置

   1. 約束文件
   <!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

    mybatis-3-config.dtd:約束文件的名稱

  2. configuration 根標簽。
-->

(5)使用mybatis的對象SqlSession,通過他的方法執行sql語句。

@Test
public void testSelect() throws Exception{
    //1.mybatis 主配置文件
    String config = "mybatis-config.xml";
    //2.讀取配置文件
    InputStream in = Resources.getResourceAsStream(config);
    //3.創建 SqlSessionFactory 對象,目的是獲取 SqlSession
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    //4.獲取 SqlSession,SqlSession 能執行 sql 語句
    SqlSession session = factory.openSession();
    //5.執行 SqlSession 的 selectList()
    List<Student> studentList = session.selectList("com.bjpowernode.dao.StudentDao.selectStudents");
    //6.循環輸出查詢結果
    studentList.forEach( student -> System.out.println(student));
    //7.關閉 SqlSession,釋放資源
    session.close();
}

2.2 在編譯的target目錄下面缺少xml的解決方式(P11)

事先做的配置

1.resource文件夾,前面需要有相應的標識,沒有的話,右鍵-Mark Directory as

2.在pom.xml文件中的<build><resources>...</resources></build>放置resource,用於掃描並將src/main/java的相應資源導入。(見操作步驟)

解決方式

1.右邊的maven,先clean,然后compile

2.上面的Build-ReBuild Project

3.上邊的File-Invalidate Caches/Restart,再點一次。

4.將sql映射文件和主配置文件直接拷貝到target目錄下面。

2.3 日志的輸出

在mybatis.xml的<configuration>后面添加

<settings>
 <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

2.4 注意事項

mybatis默認非自動提交事務,查詢不需要提交,而insert/update/delete,需要提交,sqlSession.commit();

2.5對各個對象的分析

Resource類

Resources 類,顧名思義就是資源,用於讀取資源文件。其有很多方法通過加載並解析資源文件,返回不同類型的 IO 流對象。

SqlSessionFactoryBuilder類

SqlSessionFactory 的 創 建 , 需 要 使 用 SqlSessionFactoryBuilder 對 象 的 build() 方 法 。 由於SqlSessionFactoryBuilder 對象在創建完工廠對象后,就完成了其歷史使命,即可被銷毀。所以,一般會將該 SqlSessionFactoryBuilder 對象創建為一個方法內的局部對象,方法結束,對象銷毀。

SqlSessionFactory接口

SqlSessionFactory 接口對象是一個重量級對象(系統開銷大的對象),是線程安全的,所以一個應用只需要一個該對象即可。創建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession()方法。

➢ openSession(true):創建一個有自動提交功能的 SqlSession

➢ openSession(false):創建一個非自動提交功能的 SqlSession,需手動提交

➢ openSession():同 openSession(false)

SqlSession接口

SqlSession 接口對象用於執行持久化操作。一個 SqlSession 對應着一次數據庫會話,一次會話以SqlSession 對象的創建開始,以 SqlSession 對象的關閉結束。

SqlSession 接口對象是線程不安全的,所以每次數據庫會話結束前,需要馬上調用其 close()方法,將其關閉。再次需要會話,再次創建。 SqlSession 在方法內部創建,使用完畢后關閉。

2.6 工具類

通過該工具類的靜態方法可以方便獲取SqlSession。

public class MyBatisUtils {

    private  static  SqlSessionFactory factory = null;
    static {
        String config="mybatis.xml"; // 需要和你的項目中的文件名一樣
        try {
            InputStream in = Resources.getResourceAsStream(config);
            //創建SqlSessionFactory對象,使用SqlSessionFactoryBuild
            factory = new SqlSessionFactoryBuilder().build(in);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //獲取SqlSession的方法
    public static SqlSession getSqlSession() {
        SqlSession sqlSession  = null;
        if( factory != null){
            sqlSession = factory.openSession();// 非自動提交事務
        }
        return sqlSession;
    }
}

3 MyBatis DAO代理

3.1兩種sql的執行方式

第一類是前面的方法,SqlSession直接執行selectList/update/delete/insert之類操作;

第二類是先通過SqlSession的getMapper()獲取接口Dao的實現類,然后調用接口的方法。原理是動態代理。

以select為例解釋,第一種是通過SqlSession直接執行selectList來獲取數據,第二種是SqlSession首先獲取一個StudentDao的一個實現類,該實現類可以直接調用selectStudents獲取數據。

SqlSession session = MyBatisUtil.getSqlSession();
List<Student> studentList = session.selectList("com.bjpowernode.dao.StudentDao.selectStudents");
 
StudentDao studentDao = MyBatisUtil.getSqlSession().getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectStudents();

3.2 參數的理解

3.2.1 parameterType

parameterType表示傳入的參數類型,可以省略。

3.2.2 傳入的參數在SQL語句中的使用

(1)如果傳入的是一個簡單類型(java 基本類型和 String),在SQL中,可以用#{任意字符}

<select id="selectById" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where id=#{studentId}
</select>
#{studentId} , studentId 是自定義的變量名稱,和方法參數名無關。

(2)傳入多個參數,使用@Param

接口方法:
List<Student> selectMultiParam(@Param("personName") String name,@Param("personAge") int age);

mapper 文件:
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where name=#{personName} or age 
=#{personAge}</select>

(3)傳入一個對象,#{ property,javaType=java 中數據類型名,jdbcType=數據類型名稱 },簡寫為 #{ property }

創建保存參數值的對象 QueryParam
package com.bjpowernode.vo;
public class QueryParam {
 private String queryName;
 private int queryAge;
 //set ,get 方法}
 
接口方法:
List<Student> selectMultiObject(QueryParam queryParam);

mapper 文件:
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where name=#{queryName} or age 
=#{queryAge}
</select>

(4)多個參數還可以按位置或者使用map

3.2.3 #和$的區別

  1. #使用 ?在sql語句中做占位的, 使用PreparedStatement執行sql,效率高
  2. #能夠避免sql注入,更安全。
  3. $不使用占位符,是字符串連接方式,使用Statement對象執行sql,效率低
  4. $有sql注入的風險,缺乏安全性。
  5. $:可以替換表名或者列名

3.2.4 resultType和resultMap

兩者選一,resultMap主要用於表的列和對象屬性不匹配。

<resultMap id="student2Map" type="com.bjpowernode.domain.Student2">
    <!-- 主鍵字段使用 id -->
    <id column="id" property="id2" />
    <!--非主鍵字段使用 result-->
    <result column="name" property="name2"/>
    <result column="email" property="email2" />
    <result column="age" property="age2" />
</resultMap>

<select id="selectStudents2" resultMap="student2Map">
    select id,name,email,age from student order by id
</select>

3.2.5 模糊like

例 1: java 代碼中提供要查詢的 “%力%”

接口方法:
List<Student> selectLikeFirst(String name);
mapper 文件:
<select id="selectLikeFirst" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 where name like #{studentName}
</select>
測試方法:
@Test
public void testSelectLikeOne(){
 String name="%力%";
 List<Student> stuList = studentDao.selectLikeFirst(name);
 stuList.forEach( stu -> System.out.println(stu));
}

例 2:mapper 文件中使用 like name "%" #{xxx} "%"

接口方法:
List<Student> selectLikeSecond(String name);
mapper 文件:
<select id="selectLikeSecond" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 where name like "%" #{studentName} "%"
</select>
測試方法:
@Test
public void testSelectLikeSecond(){
 String name="力";
 List<Student> stuList = studentDao.selectLikeSecond(name);
 stuList.forEach( stu -> System.out.println(stu));
}

4 動態SQL

對於 sql 中的"<",一定要換成"&lt;"。

動態 SQL 相當於會變化的 SQL,主要包括<if>,<where>,<foreach>和代碼片段。

if 可以在滿足條件時執行相應功能,where主要用於包裝if,去掉多余的and/or,foreach是對於一個可以遍歷的集合進行輸出,代碼片段表示代碼的重用功能。

示例:

4.1 if 和 where

<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 <where>
 <if test="name != null and name !='' ">
 and name = #{name}
 </if>
 <if test="age > 0 ">
 and age &gt; #{age}
 </if>
 </where>
</select>

4.2 foreach

<!--說明-->
<foreach collection="集合類型" open="開始的字符" close="結束的字符" 
item="集合中的成員" separator="集合成員之間的分隔符">
 #{item 的值}
</foreach>


<!--示例-->
<select id="selectStudentForList" 
resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 <if test="list !=null and list.size > 0 ">
 where id in
 <foreach collection="list" open="(" close=")" 
item="stuid" separator=",">
 #{stuid}
 </foreach>
 </if>
</select>

4.3 代碼片段,重用

<sql/>標簽用於定義 SQL 片斷,以便其它 SQL 標簽復用。而其它標簽使用該 SQL 片斷,需要使用<include/>子標簽。

<sql id="studentSql">
 select id,name,email,age from student
</sql> <select id="selectStudentSqlFragment" 
resultType="com.bjpowernode.domain.Student">
 <!-- 引用 sql 片段 -->
 <include refid="studentSql"/>
 <if test="list !=null and list.size > 0 ">
 where id in
 <foreach collection="list" open="(" close=")" 
item="stuobject" separator=",">
 #{stuobject.id}
 </foreach>
 </if>
</select>

5 配置文件

5.1 主配置文件

之前項目中使用的 mybatis.xml 是主配置文件。

主配置文件特點:

1.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">

2.根元素,<configuration>

3.主要包含內容:

​ 定義別名

​ 數據源

​ mapper 文件

5.2 dataSource

在主配置文件中配置,包括下面三種

  • UNPOOLED 不使用連接池的數據源,MyBatis 會創建 UnpooledDataSource 實例

  • POOLED 使用連接池的數據源,MyBatis 會創建 PooledDataSource 實例

  • JNDI 使用 JNDI 實現的數據源,MyBatis 會從 JNDI 服務上查找 DataSource 實例

<dataSource type="POOLED">
 <!--連接數據庫的四個要素-->
 <property name="driver" value="com.mysql.jdbc.Driver"/>
 <property name="url" 
value="jdbc:mysql://localhost:3306/ssm?charset=utf-8"/>
 <property name="username" value="root"/>
 <property name="password" value="123456"/>
</dataSource>

5.3 事務

使用位置,<transactionManager type="JDBC"/>

  • JDBC,使用 JDBC 的事務管理機制。默認不自動提交,需要手動提交。

  • MANAGED,由容器來管理事務的整個生命周期(如 Spring 容器)。

5.4 使用數據庫屬性配置文件

將寫在dataSource中數據庫四個要素抽取到一個文件中,主文件中換成${文件名.具體name}。

<dataSource type="POOLED">
 <!--使用 properties 文件: 語法 ${key}-->
 <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>

5.5 mapper(映射器)

1.<mapper resource=" " />

使用相對於類路徑的資源,從 classpath 路徑查找文件,

例如:<mapper resource="com/bjpowernode/dao/StudentDao.xml" />

​2. <package name=""/>

指定包下的所有 Dao 接口

如:<package name="com.bjpowernode.dao"/>

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

6 分頁

使用插件 PageHelper,對應配置如下:

  • 在pom.xml中
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.1.10</version>
</dependency>
  • 在mybatis主配置文件中,<environments>之前加入
<plugins>
 <plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>

用法

@Test
public void testSelect() throws IOException {
//獲取第 1 頁,3 條內容
 PageHelper.startPage(1,3);
 List<Student> studentList = studentDao.selectStudents();
 studentList.forEach( stu -> System.out.println(stu));
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM