1. 程式人生 > 其它 >Mybatis的入門總結

Mybatis的入門總結

1.三層架構的介紹

軟體中分層

在這裡插入圖片描述

分層的作用

  1. 降低層與層之間的耦合性。
  2. 提高軟體的可維護性。
  3. 提升軟體的可擴充套件性。

小結:

三層架構的好處

  1. 降低層與層之間的耦合性。
  2. 提高軟體的可維護性。
  3. 提升軟體的可擴充套件性。

什麼是框架

之前我們都是根據需求寫出所有的相關程式碼麻煩,累,繁瑣。框架是別人寫好的程式碼,是對常見功能的封裝,是一個半成品。我們在框架的基礎上開發出成品的軟體。

假如你要造一輛馬車,在沒有零件的情況下,你需要自己去伐木,去把木頭做成木板,木棍,然後做成輪子,門,等部件,然後組裝起來,很麻煩。框架就相當於現成的輪子,門等部件。我們只需要拿過來使用即可。

常見框架如:Spring,SpringMVC,Mybatis,JdbcTemplate,Bootstrap等等。

框架解決的問題

提升了開發效率

企業專案中使用框架,程式設計師不再需要重複造輪子,只需要專注實現業務需求,提升了開發效率。

提升了系統穩定性

一個成熟的框架,經過了在眾多企業專案中的驗證使用,穩定性有保障。

持久層框架

MyBatis是一款優秀的持久層框架,MyBatis 避免了幾乎所有的 JDBC程式碼和手動設定引數以及獲取結果集。

關於持久層的框架,還有一個封裝程度更高的框架(hibernate)。該框架相對比較重量級,以及其它各個方面的原因,目前流行程度下降了很多,企業專案中用的越來越少了。

表現層框架

SpringMVC是一種基於Java,實現了Web MVC設計模式,將Web層進行解耦。SpringMVC可以簡化我們日常Web開發。

整合的框架

Spring是一個輕量級控制反轉(IoC)和麵向切面(AOP)的容器框架。讓開發變的更簡單。

什麼是框架:框架是對常見功能的封裝

Mybatiis官方網站

http://www.mybatis.org/mybatis-3/

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-nugTPZu6-1621653693288)(C:\Users\lenovo\Desktop\java筆記\圖片檔案\Mybatis.png)]

小結:

1.Mybatis是一個持久層框架

2.Mybatis的優點:

簡單易學:不需要關注JDBC的資源獲取和釋放,配置SQL對映檔案即可

解除SQL與程式程式碼的耦合:SQL語句和程式碼分離,提高可維護性。

2.Mybatis入門搭建:

開發步驟

  1. 建立模組 hello-mybatis01
  2. 建立lib包加入Mybatis-Mysql5.7-log4j jar包
  3. 編寫使用者類
  4. 準備核心檔案:sqlMapConfig.xml檔案
  5. 編寫mapper介面(UserMapper)
  6. 編寫Mapper介面對映檔案(Usermapper.xml)
  7. 編寫測試程式碼
-- 建立表

CREATE TABLE USER (
  id INT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(20) NOT NULL,
  birthday DATE,
  sex CHAR(10) ,
  address VARCHAR(50)
);

INSERT INTO USER VALUES (NULL, '羅西','1980-10-24','男','45個分站勝利');
INSERT INTO USER VALUES (NULL, '馬奎斯','1992-11-12','女','48個GP勝利');
INSERT INTO USER VALUES (NULL, '斯通納','1983-05-20','男','51次獲勝');
INSERT INTO USER VALUES (NULL, '佩德羅薩','1995-03-22','男','52次獲勝');
INSERT INTO USER VALUES (NULL, '菲爾·雷德','1995-03-22','男','54次獲勝');
INSERT INTO USER VALUES (NULL, '6麥克·杜漢','1995-03-22','女','52次獲勝');

-- 查詢全部資料
SELECT * FROM USER;

1.環境搭建

在這裡插入圖片描述

2.編寫使用者類

/**
 使用者實體類物件 */
public class User {

    private Integer id; // 主鍵
    private String username; // 使用者名稱
    private Date birthday; // 生日
    private String sex; // 性別
    private String address; // 地址

	// 省略構造方法/getter/setter/toString
}

3.準備核心檔案:sqlMapConfig.xml檔案

注意sqlMapConfig.xml一定要在src下

<?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>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--1.3配置連線池需要的引數-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.93.222:3306/day19"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--配置介面對映檔案,包掃描-->
    <mappers>
        <package name="com.xjggb.dao"/>
    </mappers>
</configuration>

4.配置日誌檔案 log4j.properties

注意檔案也是放在src下

### 設定Logger輸出級別和輸出目的地 ###
log4j.rootLogger=debug, stdout

### 把日誌資訊輸出到控制檯 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout

5.介面的建立UserMapper的建立

package com.xjggb.dao;
import com.xjggb.entity.User;


import java.util.List;

public interface UserMapper {
    /*
    * 查詢全部
    * */
    List<User> findListUser();
    }

6.UserMapper.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.xjggb.dao.UserMapper">
    <!--
    id:介面中方法的名字
    resultType: 返回的資料型別,如果是集合型別,這裡應該指定集合中元素的型別全名
    文字:SQL語句查詢全部
    -->
    <select id="findAllUsers" resultType="com.itheima.entity.User">
           <select id="findListUser" resultType="user">
       SELECT * FROM USER;
    </select>
    </select>
</mapper>

7.測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;

import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession();
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        物件呼叫方法
        List<User> listUser = mapper.findListUser();
//        遍歷
        listUser.forEach(s-> System.out.println("s = " + s));

    }
}

8.小結

1.Mybatils:實現了SQL與程式碼分離實現瞭解耦性

2.Mybatils:避免了所有的jdbc程式碼和手動設定引數以及獲取結果集

3.用動態代理來建立物件呼叫方法,

3.Mybatils的基本使用CRUD

1.根據使用者id查詢

開發步驟:

1.編寫Usermapper介面

2.編寫Usermapper.xml配置檔案

3.測試

Usermapper介面類

public interface UserMapper {
//根據id查詢使用者
    User findUserId(int id);
}

UserMapper.xml檔案

<select id="findUserId" parameterType="int" resultType="user">
    SELECT * FROM USER WHERE id=#{uid};
</select>

測試:

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class MybatisTest01 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");

        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = builder.build(stream);
        SqlSession sqlSession = build.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User findUserBayID = mapper.findUserId(2);
        System.out.println("findUserBayID = " + userAndInfo);
    }
}


2.新增使用者

新增介面

public interface UserMapper {
    int insertUser(User user);


}

Usermapper.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.xjggb.dao.UserMapper">
    <cache/>

<!--    使用者新增資料
        id介面方法名
        parameterType 引數是型別配置檔案做了別名設定別名
-->
    <insert id="insertUser" parameterType="user" >
        insert into USER values (null,#{username},#{birthday},#{sex},#{address})
    </insert>
</mapper>

SqlMapConig.xml檔案

注意新增資料的時候會出現中文亂碼 記得新增 ?useUnicode=true&characterEncoding=UTF-8

<?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>
        <!--開啟駝峰式命名 資料庫中名字寫 user_name 對映到類中 userName-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <!--配置別名,包掃描-->
    <typeAliases>
        <package name="com.xjggb.entity"/>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--1.3配置連線池需要的引數-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.93.222:3306/day19?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--配置介面對映檔案,包掃描-->
    <mappers>
        <package name="com.xjggb.dao"/>
    </mappers>
</configuration>

測試類

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;

import java.util.List;

public class MybatisTest01 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        建立物件

        User user = new User();

//        往物件新增元素
        user.setBirthday(Date.valueOf("2019-05-01"));
        user.setAddress("我乃行健乖乖霸");
        user.setUsername("我是乖乖霸");
        user.setSex("男");

//        物件呼叫方法
        int i = mapper.insertUser(user);
//        遍歷
        System.out.println("i = " + i);

    }
}


提交事務

你新增成功資料庫看不到資料是應為事務沒有提交

方式一:手動提交

 sqlSession.commit();

方式二:自動提交

  SqlSession sqlSession = build.openSession(true);

3.根據id刪除使用者

編寫介面

package com.xjggb.dao;
import com.xjggb.entity.User;
import java.util.List;
public interface UserMapper {

    /*
    * 根據id刪除使用者
    * */
    int delectUserByid(int id);
    }

編寫UserMapper.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.xjggb.dao.UserMapper">
    <cache/>
    <!--根據使用者id刪除使用者-->
    <delete id="delectUserByid" parameterType="int">
DELETE FROM  `USER` WHERE id=#{id};

    </delete>
</mapper>    

4.修改使用者

編寫介面UserMapper.interface介面

public interface UserMapper {

    /*
    * 修改使用者
    * */
    int updateUser(User user);
    }

編寫UserMapper.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.xjggb.dao.UserMapper">
    <cache/>
    <!--使用者更新資料-->
    <update id="updateUser" parameterType="user">
        UPDATE `USER` SET username=#{username},birthday=#{birthday},sex=#{sex}, address=#{address} WHERE id=#{id}
    </update>
</mapper> 

測試類

package com.xjggb.test;


import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;

public class MybatisTest03 {

    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        建立物件
        User user = new User();
        user.setId(17);
        user.setSex("nv");
        user.setUsername("吾乃行健乖乖霸");
        user.setAddress("我乃行健乖乖霸");
        user.setBirthday(Date.valueOf("1980-10-24"));
//根據id修改資料

        int i = mapper.updateUser(user);

        if (i==1){
            System.out.println("新增成功");
        }else {
            System.out.println("新增失敗");
        }
    }
}


4.查詢新增的主鍵值

方式一:子元素(常用)

原理在insert語句執行後在執行查詢語句返回新增的主鍵id

屬性說明
keyColumn主鍵表中的欄位,user表的主鍵id列
keyProperty體類的主鍵屬性名 user中的id
resultType鍵的資料型別
order執行前 BEFORE 執行後 AFTER

編寫介面

package com.xjggb.dao;
import com.xjggb.entity.User;
import java.util.List;

public interface UserMapper {
    /*
    * 新增使用者
    * */

    int insertUser(User user);
}


編寫UserMapper.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.xjggb.dao.UserMapper">
    <cache/>
<!--    使用者新增資料
        id介面方法名
        parameterType 引數是型別配置檔案做了別名設定別名
-->
    <insert id="insertUser" parameterType="user" >
        <!-- keyColumn  主鍵表中的欄位,user表的主鍵id列
        keyProperty 實體類的主鍵屬性名  user中的id
        resultType 主鍵的資料型別
        order:
        執行前  BEFORE
        執行後  AFTER
        -->
        <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
      SELECT  LAST_INSERT_ID();
        </selectKey>
        INSERT INTO USER VALUES (null, #{username}, #{birthday}, #{sex}, #{address})
    </insert>
</mapper>

測試程式碼

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;

import java.util.List;

public class MybatisTest01 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        建立物件
        User user = new User();
//        往物件新增元素
        user.setId(null);
        user.setBirthday(Date.valueOf("2019-05-01"));
        user.setAddress("我乃行健乖乖霸");
        user.setUsername("我是乖乖霸");
        user.setSex("男");
//        物件呼叫方法
        int i = mapper.insertUser(user);
        System.out.println("i = " + user);
    }
}


方式二:在insert標籤中增加屬性
屬性說明
useGeneratedKeystrue,使用mysql生成的主鍵
keyColumn表中主鍵對應的欄位
keyProperty實體類中對應的屬性

UserMapper介面

package com.xjggb.dao;

import com.xjggb.entity.User;
import java.util.List;
public interface UserMapper {
    /*
    * 新增使用者
    * */

    int insertUser(User user);
}


UserMapper.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.xjggb.dao.UserMapper">
    <cache/>
<!--    使用者新增資料
        id介面方法名
        parameterType 引數是型別配置檔案做了別名設定別名
        keyColumn 表中主鍵對應欄位
        keyProperty 實體類對應的屬性
        useGeneratedKeys  true 使用Mysql生成的主鍵
-->
    <insert id="insertUser" parameterType="user" keyColumn="id" keyProperty="id" useGeneratedKeys="true" >

        INSERT INTO USER VALUES (null, #{username}, #{birthday}, #{sex}, #{address})

    </insert>
</mapper>

測試類

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;

import java.util.List;

public class MybatisTest01 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        建立物件
        User user = new User();
//        往物件新增元素
        user.setId(null);
        user.setBirthday(Date.valueOf("2019-05-01"));
        user.setAddress("我乃行健乖乖霸");
        user.setUsername("我是乖乖霸");
        user.setSex("男");
//        物件呼叫方法
        int i = mapper.insertUser(user);
        System.out.println("i = " + user);
    }
}


小結:

區別 :useGeneratedKeys 需要條件主鍵必須是自增,而不用

5.sqlMapConfig.xml核心配置檔案

1.properties標籤

目前我們將資料庫相關的資訊都是配置在核心配置檔案中,如果核心配置檔案中的內容很多,那麼修改的時候就不是很方便。我們可以將資料庫的配置資訊專門放到一個單獨的檔案中,使用properties標籤引入即可。

properties的作用:

將外面的屬性檔案(.properties)載入進來。在後面就可以引用屬性檔案中的鍵和值

編寫資料庫連線屬性資原始檔(jdbc.properties)

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.93.222:3306/day19?useUnicode=true&amp;characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root

編寫SqlMapConfig.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="jdbc.properties">

    </properties>

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--1.3配置連線池需要的引數-->
                <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>
        <package name="com.xjggb.dao"/>
    </mappers>
</configuration>

小結:

  1. properties作用是什麼?

    引入外部的properties檔案

  2. 內部配置的property和外面配置的properties如果同名,使用哪個?

    使用外部的

    url連線時:jdbc:mysql://192.168.93.222:3306/day19?useUnicode=true&characterEncoding=UTF-8

    一定要去掉amp;不然就會插入資料亂碼

2.typeAliases標籤設定別名

作用:

我們在介面對映檔案中指定引數或者返回值型別時,需要寫出具體的包名和類名,是比較麻煩的我們可以通過別名更簡單,比如 吉吉國王 簡稱猴子

編寫SqlMapConfig.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="jdbc.properties">

    </properties>

    <!--配置別名,包掃描-->
    <typeAliases>
        <package name="com.xjggb.entity"/>

    </typeAliases>

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--1.3配置連線池需要的引數-->
                <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>
        <package name="com.xjggb.dao"/>
    </mappers>
</configuration>

小結:

別名的設定不許要寫包名和類名

比如package com.xjggb.entity.User 直接寫成user即可

3.mappers標籤載入介面對映檔案

方式一:

單個載入

<!--對映器-->
<mappers>
    <!--
    resource: 指定類路徑下對映檔案,注:路徑使用/做為分隔符,而不是點號
    class: 指定使用註解的介面名字
     -->
    <mapper resource="mapper/UserMapper.xml"/>
</mappers>

方式二

包掃描載入mapper對映檔案

1.要求介面對映檔案,與介面放在同一個目錄

2.介面名稱和對映檔名稱一致

    <!--配置介面對映檔案,包掃描-->
    <mappers>
        <package name="com.xjggb.dao"/>
    </mappers>

小結:

1.單個載入不方便,包掃描容錯率低更適合團隊開發

2.介面名稱與對映檔案介面一致

3.mappers標籤的作用:配置介面對映檔案位置

4.開啟駝峰式命名

開啟駝峰命名的作用: 將資料庫帶有_的欄位與pojo類的屬性駝峰命名相關聯
例如pojo類有個屬性叫 userName,資料庫對應欄位叫user_name

編寫SqlMapConfig.xml檔案

    <settings>
        <!--開啟駝峰式命名 資料庫中名字寫 user_name 對映到類中 userName-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="cacheEnabled" value="true"/>
    </settings>

6.Mybatis 模糊查詢

方式一

編寫介面

public interface UserMapper {

    /*
    * 根據名稱模糊查詢
    * */
    List<User> findUserByUsername(String username);
}

編寫配置檔案UserMapper.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.xjggb.dao.UserMapper">
    <cache/>


<!--根據使用者名稱模糊查詢-->
    <select id="findUserByUsername" parameterType="string" resultType="user">
        SELECT * FROM USER WHERE username like #{name};
    </select>
</mapper>

測試類

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest04 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest04.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession();
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userByUsername = mapper.findUserByUsername("%乖霸%");
//遍歷陣列
     userByUsername.forEach(s-> System.out.println("s = " + s));

    }
}


方式二:

UserMapper.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.xjggb.dao.UserMapper">
    <cache/>


<!--根據使用者名稱模糊查詢-->
    <select id="findUserByUsername" parameterType="string" resultType="user">
        SELECT * FROM USER WHERE username like'%${value}%';
        
  </mapper>


UsrerMapper介面

public interface UserMapper {

    /*
    * 根據名稱模糊查詢
    * */
    List<User> findUserByUsername(String username);
}

測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest04 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest04.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession();
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userByUsername = mapper.findUserByUsername("乖霸");
//遍歷陣列
     userByUsername.forEach(s-> System.out.println("s = " + s));

    }
}


小結:

#{} 先使用?佔位,後賦值

當引數是基本資料型別或者包裝類或者String

#{隨便寫}

當引數是自定義型別

#{物件的屬性名}

${value}

當引數是基本資料型別

​ ${value}

​ 當引數是自定義型別User

​ ${物件的屬性名}

7.介面對映檔案:

1.resultType輸出型別

1.簡單型別
<!-- 統計使用者表中的女生的使用者數量 -->
<select id="getAmountBySex" resultType="int" parameterType="string">
    select count(*) from user where sex=#{sex}
</select>

2.POJO型別
  <!--根據使用者id查詢資料-->
<select id="findUserId" parameterType="int" resultType="user">
    SELECT * FROM USER WHERE id=#{uid};
</select>

小結

resultType的輸出型別有哪兩種?

  1. 簡單型別 八大資料型別
  2. POJO

注意:

​ parameterType引數型別全部可以省略

​ resultType返回值型別全部不能省略

2.resultMap輸出對映

Mybatis可以把查詢的結果集自動封裝為物件,但是有要求,資料庫得到列名稱,要以物件的額屬性一致,否則不能正確封裝資料

查詢的列與物件屬性不一致的時候,使用resultMap解決,

配置mapper對映檔案

  1. 定義resultMap標籤
  2. id標籤:對映主鍵欄位,如果列名與屬性名相同可以省略
  3. result標籤:對映普通欄位,指定哪個屬性對應哪個列
  4. 在查詢的結果中使用resultMap

Usermapper介面

public interface UserMapper {
    /*
     * 根據id查詢資料
     * */
    User findUserByid(int id);
    }

Usermapper.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.xjggb.dao.UserMapper">
    <cache/>



<!--對結果集對映-->
    <resultMap id="rml" type="user">
<!--        對查詢結果欄位和類中的成員變數進行對映-->
<!--        id 主鍵的對映-->
<!--        result 普通欄位的對映-->
<!--        column 查詢列名 -->
<!--        property 物件的成員變數名 -->
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="birthday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
    </resultMap>
<!--    根據使用者查詢id-->
    <select id="findUserByid" parameterType="int"  resultMap="rml">
        select * from USER where id=#{id}

    </select>
 </mapper>

測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest05 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest05.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession();
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User userByid = mapper.findUserByid(5);
        System.out.println("userByid = " + userByid);
    }
}


小結:

resultMap的作用:當實體類的屬性跟資料庫欄位不一致的時候可以用resultMap來對映結果集

8.動態SQL

動態SQL指的是:在程式執行時,根據傳入的引數情況,拼接最終執行的sql語句。

比如淘寶的條件的篩選 價格高低,銷量最高等等

1.動態SQL:if標籤

根據使用者和性別查詢使用者

動態SQL語句:if標籤的使用

if標籤的格式

<if test="條件">
  SQL語句
</if>

if標籤的作用:滿足條件就拼接這個SQL

條件全部輸入

編寫介面

public interface UserMapper {
    /*
    * 動態查詢
    * */
    List<User> findUserByNameAndSex(User user);
    }

編寫配置檔案

  
    <select id="findUserByNameAndSex" parameterType="user" resultType="user">
        select * from USER where  username=#{username} and sex=#{sex}
    </select>


測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest06 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest06.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession();
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

//       建立物件
        User user = new User();
        user.setSex("男");
        user.setUsername("羅西");
        List<User> userByNameAndSex = mapper.findUserByNameAndSex(user);
        userByNameAndSex.forEach(s-> System.out.println("s = " + s));
    }
}


小結

只有輸入全部條件才能查詢輸入單個條件的時候什麼都查不到,sql沒有拼接成功

動態SQL的使用

  1. if:判斷使用者名稱稱不為空,且不為空字串,則使用者名稱稱作為查詢條件
  2. if:判斷使用者性別不為空,且不為空字串,則使用者性別作為查詢條件

UserMapper.xml配置檔案

    <select id="findUserByNameAndSex" parameterType="user" resultType="user">

        select * from USER where 
        <if test="username!=null and username!=''">
            username like '%${username}%'
        </if>
        <!--&&與操作要轉義  &amp; &amp;-->
        <if test="sex!=null &amp;&amp; sex!=''"></if>
        and sex=#{sex}
    </select>


小結:

if標籤不能去掉and或者or

2.where標籤的作用

where標籤作用

  1. 相當於where關鍵字,自動補全where這個關鍵字
  2. 去掉多餘的and和or關鍵字
  3. 標籤寫在裡面

UserMapper.xml檔案

   <select id="findUserByNameAndSex" parameterType="user" resultType="user">
        select * from USER
        <where>
            <if test="username!=null and username!=''">
                username like #{username}
            </if>
            <!--&&與操作要轉義  &amp; &amp;-->
            <if test="sex!=null &amp;&amp; sex!=''">
                AND sex=#{sex} 
            </if>  
        </where>
    </select>

小結

where標籤的作用相當於whrer關鍵字:

1.需要的時候就加上

2.可以去掉多餘的AND 和OR

3.建議if標籤和whrer標籤一起使用

4.當全部條件都不輸入就會全表掃描

3.動態SQL:set標籤

set標籤的作用

  1. 用在update語句中,相當於set關鍵字
  2. 去掉SQL程式碼片段中後面多餘的逗號

有經驗得都知道資料更新部分的時候不更新的資料就會變成null

編寫UserMapper介面

   /*
    * 修改使用者
    * */
    int updateUser(User user);

編寫Usermapper.xml檔案

    <!--使用者更新資料-->
    <update id="updateUser" parameterType="user">
        UPDATE `USER` SET username=#{username},birthday=#{birthday},sex=#{sex}, address=#{address} WHERE id=#{id}

    </update>

測試

package com.xjggb.test;


import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;

public class MybatisTest03 {

    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        建立物件
        User user = new User();
        user.setId(17);
        user.setSex("nv");
        user.setUsername("吾乃行健乖乖霸");
        user.setAddress("我乃行健乖乖霸");
        user.setBirthday(Date.valueOf("1980-10-24"));
//根據id修改資料

        int i = mapper.updateUser(user);

        if (i==1){
            System.out.println("修改成功");
        }else {
            System.out.println("修改失敗");
        }


    }
}


小結:

按部分更新的時候更新成功後,其他的欄位就會為null值

這樣存在問題,沒有值的欄位也會被更新為null,最好是有資料的欄位更新,沒有資料的欄位不更新。

使用set標籤進行判斷,如果有值就更新,沒有值就不更新。

 <!--使用者更新資料-->
    <update id="updateUser" parameterType="user">
       UPDATE `USER`
       <set>
           <if test="username!=null and username!=''">
               username=#{username},
           </if>

           <if test="birthday!=null">
               birthday=#{birthday},
           </if>
           <if test="sex!=null and sex!=''">
               sex=#{sex},
           </if>
           <if test="address!=null and address!=''">
               address=#{address}
           </if>
       </set>
        where id=#{id}
    </update>


小結:

set標籤的作用:

1.表示Set關鍵字去掉多餘的逗號

2.有值就更新,沒有值就不更新

9.foreach標籤的使用

方式一

foreach標籤:遍歷陣列得到基本型別的資料

實現批量刪除使用者

介面

    /*
    * 批量刪除使用者
    * */
int deleteUserList(int[] id);

對映檔案

    <!--批量的刪除使用者-->
    <delete id="deleteUserList" parameterType="list">
        delete from USER where
        <!--
    collection: 取值為array表示遍歷的是陣列
    open: 遍歷前新增的符號
    close: 遍歷最後新增的符號
    separator:分隔符
    item: 表示每個元素的變數名
-->
        <foreach collection="array" open="id in (" close=");" separator="," item="temp">
            #{temp}
        </foreach>

    </delete>


測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest07 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest07.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        int[] o={28,29,30};
        int i = mapper.deleteUserList(o);
        System.out.println("i = " + i);
    }
}


小結

foreach標籤:遍歷陣列或集合

  • collection:指定遍歷的是陣列還是集合 array表示陣列
  • open:迴圈前的內容
  • close:迴圈後的內容
  • item:每次迴圈遍歷到的資料
  • separator:每次迴圈後拼接的內容
方式二

儲存多個使用者到資料庫中

介面

    /*
    * 同時新增多個使用者
    * */
    int addUsers(List<User> listUser);

對映檔案

    <!--同時新增多個使用者-->
    <insert id="addUsers" parameterType="list">
        <!--
        collection 要遍歷的集合使用list
        item 設定變數名,代表每個遍歷的元素
        separator 每次遍歷完後新增一個分隔符
        #{變數名.屬性} 來引用每個屬性中的值
        -->
        INSERT INTO USER VALUES
       <foreach collection="list" item="user" separator=",">
           (null, #{user.username}, #{user.birthday}, #{user.sex}, #{user.address})
       </foreach>
    </insert>

測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

public class MybatisTest08 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest08.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = new ArrayList<>();
        users.add(new User(null,"牛魔王", Date.valueOf("1980-01-30"),"男","火焰山"));
        users.add(new User(null,"紅孩兒", Date.valueOf("2009-05-08"),"男","火雲洞"));
        users.add(new User(null,"玉面狐狸", Date.valueOf("2005-11-01"),"女","狐狸洞"));

        mapper.addUsers(users);
    }
}


小結

foreach:迴圈添拼接內容

  • collection:指定遍歷的是集合或陣列, list表示遍歷集合
  • item:迴圈遍歷到的一個元素
  • separator:分隔符,每次迴圈後拼接的內容

注意:取資料需要 #{user.username}

10.sql和include標籤

我們發現在介面對映檔案中會出現很多相同的SQL語句,每個地方都寫一遍有些麻煩。我們可以把相同的SQL語句抽取出來,在需要的地方引入即可。

sql和include標籤的作用

  1. sql標籤:定義一段SQL語句,起個名字可以重用。
  2. include標籤:引入上面定義的SQL程式碼段。
    <!--抽取重複程式碼-->
    <sql id="listUser">
          INSERT INTO USER VALUES
    </sql>

    <!--同時新增多個使用者-->
    <insert id="addUsers" parameterType="list">
    <!-- 引用抽取的程式碼-->
      <include refid="listUser"/>
        <!--
        collection 要遍歷的集合使用list
        item 設定變數名,代表每個遍歷的元素
        separator 每次遍歷完後新增一個分隔符
        #{變數名.屬性} 來引用每個屬性中的值
        -->
       <foreach collection="list" item="user" separator=",">
           (null, #{user.username}, #{user.birthday}, #{user.sex}, #{user.address})
       </foreach>
    </insert>

小結

  1. sql標籤的作用:抽取一段sql語句
  2. include標籤的作用:引用抽取的SQL語句

11.多表關聯

回顧表的關係

  1. 一對一關聯

    任何身份證的關係

    中國的夫妻關係

  2. 一對多關聯關係

    一個使用者有多個訂單

    一個老師可以有多個學生

  3. 多對多關聯

    老師與學生:一個老師教多個學生,一個學生也可以跟多個老師學習

    使用者與角色:一個使用者多個角色,一個角色多個使用者

    實際開發中專案中,多對多的關係通過中間表,看成兩個一對多關聯關係

一對一關聯

使用者的擴充套件資訊

CREATE DATABASE day19;
USE day19;

-- 建立使用者基本表
CREATE TABLE USER (
  id INT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(20) NOT NULL,
  birthday DATE,
  sex CHAR(1) DEFAULT '男',
  address VARCHAR(50)
);

INSERT INTO USER VALUES (NULL, '孫悟空','1980-10-24','男','花果山水簾洞');
INSERT INTO USER VALUES (NULL, '白骨精','1992-11-12','女','白虎嶺白骨洞');
INSERT INTO USER VALUES (NULL, '豬八戒','1983-05-20','男','福臨山雲棧洞');
INSERT INTO USER VALUES (NULL, '蜘蛛精','1995-03-22','女','盤絲洞');
 

-- 使用者擴充套件資訊表,一個使用者對應一條使用者擴充套件資訊
CREATE TABLE user_info (
   id INT PRIMARY KEY,   -- 既是主鍵又是外來鍵
   height DOUBLE,  -- 身高釐米
   weight DOUBLE,   -- 體重公斤
   married TINYINT,    -- 是否結婚,1為結婚,0為未婚
   FOREIGN KEY (id) REFERENCES USER(id)
);

-- 插入使用者擴充套件資訊表
INSERT INTO user_info VALUES(1,185,90,1),(2,170,60,0);


開發流程

  1. 編寫實體類
  2. 編寫介面
  3. 編寫對映檔案
  4. 測試

實體類

public class User implements Serializable {
    private Integer id; // 主鍵
    private String username; // 使用者名稱
    private Date birthday; // 生日
    private String sex; // 性別
    private String address; // 地址

//    一個使用者包含一個
    private UserInfo userInfo;
//省略getset方法
}

public class UserInfo {
    private Integer id; // 主鍵
    private Double height; // 身高
    private Double weight; // 體重
    private Boolean married; // 是否結婚
    //省略getset方法
}

編寫介面

package com.xjggb.dao;

import com.xjggb.entity.User;

public interface UserinfoMapper {

    /*
     * 查詢使用者的擴充套件資訊
     * */
    User findUserAndInfo(int uid);
    
}

編寫配置檔案

association標籤的作用:用來指定類的一對一關聯關係

association標籤屬性 :

property :指定另一方的物件屬性名字 如userInfo

javaType:指定另一方的類名

    <resultMap id="userAndInfo" type="user" >
<!--        id主鍵的對映
            result普通欄位的對映
            column 資料庫列名
            property 物件屬性名
-->
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="birthday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
<!--        一對一關聯  user包含一個Userinfo類-->
        <association property="userInfo" javaType="com.xjggb.entity.UserInfo">
            <id column="id" property="id"/>
            <result column="height" property="height"/>
            <result column="weight" property="weight"/>
            <result column="married" property="married"/>
        </association>
    </resultMap>

    <select id="findUserAndInfo" parameterType="int" resultMap="userAndInfo">
SELECT * FROM `USER` u INNER JOIN user_info f ON u.id=f.id WHERE u.id=#{id};
    </select>

測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.User;
import com.xjggb.entity.UserInfo;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

public class MybatisTest09 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest09.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);

        User userAndInfo = mapper.findUserAndInfo(1);
        System.out.println("userAndInfo = " + userAndInfo);
    }
}


注意關聯的時候使用resultMap標籤封裝結果時,即使欄位名和類名的屬性相同用也需要指定這樣太麻煩了

可以用autoMapping=“true”

    <resultMap id="userAndInfo" type="user" autoMapping="true">
        <id column="id" property="id"/>
        <!--
    association:一對一關聯關係,對另一個物件的對映
    property: 一對一類中的成員變數名
    javaType: 一對一類中的型別
-->
        <association property="userInfo" javaType="com.xjggb.entity.UserInfo" autoMapping="true">
            <id column="id" property="id"/>
        </association>
    </resultMap>
    <select id="findUserAndInfo" parameterType="int" resultMap="userAndInfo">
SELECT * FROM `USER` u INNER JOIN user_info f ON u.id=f.id WHERE u.id=#{id};
    </select>

小結

1.一對一關聯實體類的關係

public class User implements Serializable {
    private Integer id; // 主鍵
    private String username; // 使用者名稱
    private Date birthday; // 生日
    private String sex; // 性別
    private String address; // 地址

//    一個使用者包含一個
    private UserInfo userInfo;
//省略getset方法
}

2.一對一的關聯標籤

3.當資料欄位和屬性名相同時 resultMap欄位對映的時候可以用autoMapping="true"屬性不要漏掉id有可能會報錯

一對多關聯

查詢使用者的多個訂單

collection的屬性說明
property多方屬性的名稱比如 orderForms
javaType屬性的型別
ofType每個元素的型別

開發步驟

  1. 建立資料表
  2. 編寫實體類
  3. Mapper介面新增方法
  4. 介面配置檔案SQL
  5. 測試

建立資料表

-- 建立訂單表
CREATE TABLE order_form (
    oid INT PRIMARY KEY AUTO_INCREMENT ,   -- 主鍵
    user_id INT NOT NULL,   -- 使用者id,外來鍵
    number VARCHAR(20),   -- 訂單編號
    create_time DATETIME,  -- 下單時間
    note VARCHAR(100),   -- 備註
    FOREIGN KEY(user_id) REFERENCES USER(id)   -- 外來鍵約束,關聯主表的主鍵
);

-- 新增訂單資料
INSERT INTO order_form VALUES(NULL, 1,'10001001', NOW(), '小米9袋'),(NULL, 1,'10001002', NOW(), '9袋小米'),(NULL, 1,'10001003', NOW(), '小米9手機');
INSERT INTO order_form VALUES(NULL, 2,'10001004', NOW(), '逃生錘'),(NULL, 2,'10001005', NOW(), '安全帶');

實體類

public class User implements Serializable {
    private Integer id; // 主鍵
    private String username; // 使用者名稱
    private Date birthday; // 生日
    private String sex; // 性別
    private String address; // 地址

//    一個使用者包含一個
    private UserInfo userInfo;
    
//    一個使用者多個訂單
    private List< OrderForm> orderForms;
// 省略getset方法    

public class OrderForm {
    private Integer oid;  //主鍵
    private Integer userId;  //外來鍵
    private String number;  //訂單號
    private Timestamp createTime; //下單時間
    private String note;  //備註資訊
    // 省略getset方法  

編寫介面

    /*
    * 查詢使用者的訂單
    * */
User findUserListOrdrForm(int oid);

編寫配置檔案

    <resultMap id="mappingUserAndOrderForm" type="user">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="birthday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>

        
        <collection property="orderForms" javaType="List" ofType="OrderForm">
            <id column="oid" property="oid"/>
            <result column="userId" property="userId"/>
            <result column="number" property="number"/>
            <result column="create_time" property="createTime"/>
            <result column="note" property="note"/>
        </collection>
    </resultMap>
    <select id="findUserListOrdrForm" parameterType="int" resultMap="mappingUserAndOrderForm">
SELECT * FROM `USER` u JOIN order_form f ON u.id=f.`user_id` WHERE u.id=#{oid}
        
    </select>


測試

package com.xjggb.test;

import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class MybatisTest10 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest10.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);

        User userListOrdrForm = mapper.findUserListOrdrForm(1);
        System.out.println("userListOrdrForm = " + userListOrdrForm);
    }
}


小結:

1.實體類的配置關係

public class User implements Serializable {
    private Integer id; // 主鍵
    private String username; // 使用者名稱
    private Date birthday; // 生日
    private String sex; // 性別
    private String address; // 地址
//    一個使用者包含一個
    private UserInfo userInfo; 
//    一個使用者多個訂單
    private List< OrderForm> orderForms;
// 省略getset方法   

2.使用collection標籤配置一對多

多對多關聯

多對多關聯關係,可以通過中間表看成兩個雙向的一對多關聯關係。

使用者與角色多對多關係模型

一個使用者對應多種角色
一種角色可以有多個使用者

多對多的關係

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-hrtzfKZJ-1621653693299)(H:\學習筆記\java筆記\圖片檔案\對對多.jpg)]

實體類

public class Role {
    private Integer roleId;
    private String roleName;
    private String roleDetail;
//一個角色多個使用者
   private List<User> users;

public class User implements Serializable {
    private Integer id; // 主鍵
    private String username; // 使用者名稱
    private Date birthday; // 生日
    private String sex; // 性別
    private String address; // 地址

//    一個使用者包含一個
    private UserInfo userInfo;

//    一個使用者多個訂單
    private List< OrderForm> orderForms;
//一個使用者多個角色
    private List<Role> roles;

編寫介面

    /**
     通過 uid 查詢使用者和他的所有角色
     */
    User findRolesByUserId(int uid);

    /**
     通過 role_id 查詢角色和他的所有使用者
     */
    Role findUsersByRoleId(int roleId);

編寫xml檔案

    <!--多對多查詢-->

        <resultMap id="useRoleMapMore" type="user">
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="birthday" column="birthday"/>
            <result property="sex" column="sex"/>
            <result property="address" column="address"/>

            <collection property="roles" javaType="list" ofType="Role">
                <id property="roleId" column="role_id"/>
                <result property="roleName" column="role_name"/>
                <result property="roleDetail" column="role_detail"/>
            </collection>
        </resultMap>
        <!--多對多,通過使用者id查詢到一個使用者裡面的多個角色-->
        <select id="findRolesByUserId" parameterType="int" resultMap="useRoleMapMore">
        SELECT u.*, r.* FROM USER u INNER JOIN user_role ur ON u.id = ur.user_id INNER JOIN role r ON ur.role_id = r.role_id WHERE u.id = #{id};
    </select>


        <resultMap id="us" type="role">
            <id property="roleId" column="role_id"/>
            <result property="roleName" column="role_name"/>
            <result property="roleDetail" column="role_detail"/>

            <collection property="users" javaType="list" ofType="User">
                <id property="id" column="id"/>
                <result property="username" column="username"/>
                <result property="birthday" column="birthday"/>
                <result property="sex" column="sex"/>
                <result property="address" column="address"/>
            </collection>
        </resultMap>
        <!--多對多,通過使用者id查詢到一個使用者裡面的多個角色-->
        <select id="findUsersByRoleId" parameterType="int" resultMap="us">
        SELECT u.*, r.* FROM USER u INNER JOIN user_role ur ON u.id = ur.user_id INNER JOIN role r ON ur.role_id = r.role_id WHERE r.role_id = #{id};
    </select>

測試

package com.xjggb.test;

import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.Role;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest11 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest11.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);

        User rolesByUserId = mapper.findRolesByUserId(1);
        List<Role> roles = rolesByUserId.getRoles();
        roles.forEach(s-> System.out.println("s = " + s));


        System.out.println("rolesByUserId = " + rolesByUserId.getRoles());
    }
}


package com.xjggb.test;

import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.Role;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest12 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest12.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession(true);
//        通過動態代理建立物件
        UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);

        Role usersByRoleId = mapper.findUsersByRoleId(1);
        List<User> users = usersByRoleId.getUsers();
        users.forEach(s-> System.out.println("s = " + s));
    }
}


小結

1.多對多在實體類中就是配置兩個一對多

    private Integer id; // 主鍵
    private String username; // 使用者名稱
    private Date birthday; // 生日
    private String sex; // 性別
    private String address; // 地址

//一個使用者多個角色
    private List<Role> roles;

    private Integer roleId;
    private String roleName;
    private String roleDetail;
//一個角色多個使用者
   private List<User> users;


2.多對多需要兩條sql按照使用者id 或者角色id進行查詢

12.Mybatis懶載入

一對一延遲載入

延遲載入介紹

延遲載入概念:也叫懶載入。指的是按需載入,在實際用到資料的時候才載入。

如:查詢使用者資訊,不需要他的擴充套件資訊。但後面有可能又需要用到,這時候可以通過延遲載入來實現。當需要擴充套件資訊的時候,再發送一條SQL語句來查詢擴充套件資訊。好處是,只有在需要的時候才查詢相應資料。提升查詢的效率。相當於每次只查詢1張表,而不是一次使用表連線查詢所有的資訊。

一對一關聯查詢使用標籤:association

一對多關聯查詢使用標籤:collection

要求

  1. 通過id查詢1號使用者User的基本資訊

  2. 使用延遲載入的方式,關聯查詢出對應的使用者擴充套件資訊UserInfo

SQL語句分析

SELECT * FROM USER WHERE id=1;
SELECT * FROM user_info WHERE id=1;

介面檔案

/**
 持久層介面:UserMapper 
 */
public interface UserMapper {

    /**
     通過id查詢1個使用者
     */
    User findUserById(int id);

    /**
     通過id查詢1個使用者擴充套件資訊
     */
    UserInfo findUserInfoById(int id);
}

mapper.xml檔案

  <resultMap id="useMapOne" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>

        <!--一對一關聯關係,User類中包含一個UserInfo類,名稱為userInfo-->
        <association property="userInfo" column="id" javaType="UserInfo" select="findUserInfoById" fetchType="lazy"/>
    </resultMap>

    <select id="findUserById" parameterType="int" resultMap="useMapOne">
        SELECT * FROM USER WHERE id=#{uid};
    </select>

    <select id="findUserInfoById" parameterType="int" resultType="UserInfo">
        SELECT * FROM user_info WHERE id=#{uid};
    </select>

x小結:

一對一延遲載入需要將一個SQL拆成兩個SQL

  1. 通過id查詢使用者物件
  2. 輸出使用者名稱和性別的屬性

注意:

不要使用斷點除錯,無法看到懶載入

不要直接輸出user物件,因為會觸發toString()方法,導致立即載入userInfo物件

@Test
public void testFindUserAndInfo() {
    User user = userMapper.findUserById(1);
    System.out.println(user.getUsername());
    System.out.println("----------------");
    
    //然後在檢視延遲載入的資料
      System.out.println(user.getUserInfo());
}

<resultMap id="userAndInfo" type="user" autoMapping="true">
    <!--association 一對一關係配置
        property: 一方的成員變數名
        javaType: 一方的型別
        select: 要執行的SQL語句,通過這個SQL語句會得到UserInfo
        fetchType: lazy表示懶載入, eager表示立即載入
        column: 第一個sql語句結果的某個欄位,作為第二個sql語句的引數
    -->
    <association property="userInfo" javaType="UserInfo" select="findUserInfoById" column="id" fetchType="lazy"></association>
</resultMap>

<select id="findUserById" resultMap="userAndInfo">
    SELECT * FROM USER WHERE id=#{uid};
</select>

<!--查詢擴充套件資訊-->
<select id="findUserInfoById" resultType="UserInfo">
    SELECT * FROM user_info WHERE id=#{infoId};
</select>

一對多延遲載入

association標籤

association標籤的屬性說明
property一方的成員變數名
column第一個sql語句結果的某個欄位,作為第二個sql語句的引數
select懶載入的sql語句
fetchTypelazy: 懶載入

eager: 立即載入

表連線查詢一次性查出所有資料。

SELECT * FROM USER u INNER JOIN order_form o ON u.id = o.user_id WHERE u.id=1;

分成兩個SQL語句

--  查詢1號使用者資料
SELECT * FROM USER WHERE id=1;

--  查詢1號使用者的訂單表,使用延遲載入方式實現
SELECT * FROM order_form WHERE user_id=1;

新增介面

/**
 通過id查詢1個使用者
 */
User findUserById(int id);

/**
通過userId查詢這個使用者所有的訂單資訊
*/
List<OrderForm> findOrdersByUserId(int userId);

   <resultMap id="useMapOne" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>

    
        <!--多對多,通過使用者id查詢到一個使用者裡面的多個角色-->
        <collection property="orders" column="id" javaType="List" ofType="OrderForm" select="findOrdersByUserId" fetchType="lazy"/>
    </resultMap>

    <select id="findUserById" parameterType="int" resultMap="useMapOne">
        SELECT * FROM USER WHERE id=#{uid};
    </select>
    <select id="findOrdersByUserId" parameterType="int" resultType="OrderForm">
        SELECT * FROM order_form WHERE user_id=#{uid};
    </select>


配置sqlMapConfig.xml,開啟MyBatis延遲載入

如果有多個延遲載入需要配置。可以在sqlMapConfig.xml核心配置檔案中統一配置一次即可

開啟延遲載入的settings中的lazyLoadingEnabled

<!--全域性設定-->
<settings>
    <!--開啟延遲載入-->
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

小結

  1. 一對多延遲載入需要將一個SQL拆成兩個SQL

    -- 先載入使用者的基本資訊
    SELECT * FROM USER WHERE id=1;
    -- 再懶載入多個訂單
    SELECT * FROM order_form WHERE user_id=1;
    
    
  2. 配置延遲載入屬性

<resultMap id="userAndInfo" type="user" autoMapping="true">
    <!--collection 一對多關係配置
    -->
    <collection property="orderForms" javaType="list" ofType="orderform" select="findOrdersByOrderId" column="id" ></collection>
</resultMap>

collection標籤的屬性

collection標籤的屬性說明
property多方的屬性名
column這個查詢結果的指定欄位值作為下一個查詢的SQL的引數
select下個查詢懶載入

13.Mybatis快取

一級快取

現在我們每次執行相同的SQL語句都是去資料庫中查詢,存在效率問題。Mybatis提供了快取方案可以提高重複查詢資料的效率。

Mybatis快取介紹

Mybatis 框架提供了快取策略,通過快取策略可以減少查詢資料庫的次數,提升系統性能。在 Mybatis 框架中
快取分為一級快取和二級快取。

一級快取是 sqlSession 範圍的快取,只能在同一個 sqlSession 內部有效。它本身已經存在,一級快取不需要手動處理,可以直接使用

小結

  1. 快取有什麼好處?

    相同的sql語句避免頻繁的訪問資料庫,使用快取效率高

  2. 一級快取的範圍?

    每個SqlSession內部都有一個一級快取

  3. 一級快取何時失效?

    增刪改提交事務,手動清除

二級快取

二級快取概述

二級快取是 mapper 對映級別快取,作用範圍跨越SqlSession,即可以在多個 SqlSession 之間共享二級快取
資料。

二級快取關鍵點

  1. 實體類需要實現Serializable介面
  2. 至少要準備2個SqlSession,再進行測試。

配置二級快取

在sqlMapConfig.xml配置

    <settings>
        <!--開啟駝峰式命名 資料庫中名字寫 user_name 對映到類中 userName-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
<!--        開啟二級快取-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

在mapper.xml檔案

 <mapper namespace="com.itheima.dao.UserMapper">
    <!--開啟二級快取,當前Mapper裡的所有查詢的資料都會放入二級快取中-->
    <cache/>
    
    <select id="findUserById" parameterType="int" resultMap="useMapOne">
        SELECT * FROM USER WHERE id=#{uid};
    </select>
</mapper>

14.註解開發

1.查詢使用者的全部資料

編寫介面

    /*
    * 使用者的全部資料
    * */
    @Select("select * from USER")
   List<User> queryListUser();

SqlMapconfig.xml檔案

  <!--配置介面對映檔案,包掃描-->
    <mappers>
        <package name="com.xjggb.dao"/>
    </mappers>

測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.dao.UserMapper01;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest13 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest13.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession();
//        通過動態代理建立物件
        UserMapper01 mapper = sqlSession.getMapper(UserMapper01.class);
        List<User> users = mapper.queryListUser();
        users.forEach(s-> System.out.println("s = " + s));
    }
}


2.使用@Results和@Result屬性

使用註解方式對結果集對映

註解說明會

註解屬性說明
@Results相當於resultMap表示對結果集的對映
@Resultcolumn
properly
id=true
查詢的欄位名
類中的成員變數名
表示主鍵

編寫介面

    /*
    * 使用者的全部資料
    * */

    @Select("select * from USER")
    @Results({  @Result(id = true , column = "id",property = "id"),
            @Result(column ="username" ,property = "username"),
            @Result(column ="birthday" ,property = "birthday"),
            @Result(column ="sex" ,property = "sex"),
            @Result(column ="address" ,property = "address")
    })
   List<User> queryListUser();

測試

package com.xjggb.test;

import com.xjggb.dao.UserMapper;
import com.xjggb.dao.UserMapper01;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class MybatisTest13 {
    public static void main(String[] args) {
        //載入配置檔案
        InputStream stream = MybatisTest13.class.getResourceAsStream("/sqlMapConfig.xml");
//        會話工廠建造類
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        會話工廠
        SqlSessionFactory build = builder.build(stream);
//        會話
        SqlSession sqlSession = build.openSession();
//        通過動態代理建立物件
        UserMapper01 mapper = sqlSession.getMapper(UserMapper01.class);
        List<User> users = mapper.queryListUser();
        users.forEach(s-> System.out.println("s = " + s));
    }
}


小結

@Select註解作用?

存放查詢的SQL語句

@Results註解作用?

相當於resultMap標籤,對查詢結果進行對映

@Result註解作用?

將一個欄位對映到類中的成員變數

3.根據使用者id修改使用者(@Update)

UserMapper介面:新增修改資料方法,在方法上使用註解@Update(“SQL語句”)

介面

/*
根據使用者Id修改使用者
 */
@Update("UPDATE user SET username=#{username}, birthday=#{birthday}, sex=#{sex}, address=#{address} WHERE id=#{id}")
void updateUser(User user);

4.根據使用者id刪除使用者(@Delete)
/*
根據使用者id刪除使用者
 */
@Delete("DELETE FROM user WHERE id=#{id}")
void deleteUser(Integer id);

5.新增使用者(@Insert)
/*
新增使用者
 */
@Insert("INSERT INTO user VALUES (NULL, #{username}, #{birthday}, #{sex}, #{address});")
void addUser(User user);

小結

註解開發的步驟

  1. 在介面中新增一個方法
  2. 給方法配置註解
  3. 在註解中寫SQL語句
  4. 測試

15.獲取新增主鍵值@SelectKey

目標

使用註解方式獲取新增資料後的主鍵

方式一
<insert id="addUser2" parameterType="user">
    INSERT INTO user (username, birthday, sex, address) VALUES (#{username}, #{birthday}, #{sex}, #{address});

    <selectKey resultType="int" keyColumn="id" keyProperty="id">
        SELECT last_insert_id();
    </selectKey>
</insert>

方式二
屬性說明
statement要執行的SQL語句:select last_insert_id()
keyProperty實體類中主鍵的屬性
keyColumn表中主鍵的列名
resultType主鍵的資料型別
beforefalse 表示after,true表示before
/*
新增使用者
 */
@Insert("INSERT INTO user VALUES (NULL, #{username}, #{birthday}, #{sex}, #{address});")
@SelectKey(statement = "SELECT LAST_INSERT_ID();", keyColumn = "id", keyProperty = "id", resultType = int.class, before = false)
void addUser(User user);

Mybatis註解小結

在註解方式實現基本CRUD操作中,使用的註解有:

註解描述
@Select配置查詢的SQL語句
@Results對查詢的結果進行對映相當於resultMap標籤
@Result對一個欄位進行對映
@Update配置修改的SQL語句
@Delete配置刪除的SQL語句
@Insert配置新增的SQL語句
@SelectKey獲取自增主鍵

16.註解實現:

一對一關聯查詢

MyBatis框架中除了使用XML配置檔案實現關係對映之外,也可以使用註解實現複雜的關係對映(一對一關聯查詢,一對多關聯查詢)。

複雜關係對映註解介紹

註解描述對應xml配置標籤
@One用於一對一關聯對映association
@Many用於一對多的關聯對映collection

介面

public interface UserMapper {
    /**
     通過id查詢1個使用者
     */
    User findUserById(int id);
    /**
     通過id查詢1個使用者擴充套件資訊,1對1
     */
    UserInfo findUserInfoById(int id);

    /**
     通過userId查詢這個使用者所有的訂單資訊,1對多
     */
    List<OrderForm> findOrdersByUserId(int userId);
}


查詢1個使用者資料,並且採用延遲載入關聯查詢出使用者擴充套件資料

  1. 編寫方法:通過id查詢使用者擴充套件資訊

    1. 方法名:findUserInfoById
    2. 使用@Select註解編寫SQL語句
  2. 編寫方法:通過id查詢1個使用者

    1. 方法名:findUserById
    2. @Select編寫查詢
    3. @Results配置1對1關聯對映
public interface UserMapper {
    // 通過uid查詢使用者和擴充套件資訊
    @Select("SELECT * FROM user WHERE id=#{uid}")
    @Results({
            @Result(property = "id", column = "id", id = true), // 主鍵對映
            @Result(property = "userInfo", column = "id", javaType = UserInfo.class,
                    // select表示要查詢的方法名 fetchType指定為LAZY表示延遲載入
                    one = @One(select = "findUserInfoById", fetchType = FetchType.LAZY))
    })
    User findUserById(int uid);
    // 通過uid查詢使用者和擴充套件資訊
    @Select("SELECT * FROM user_info WHERE id=#{uid}")
    UserInfo findUserInfoById(int uid);
}

一對多關聯查詢

關聯查詢出1號使用者全部訂單資料

erMapper介面

  1. 通過user_id查詢當前使用者訂單的方法

    1. 編寫findOrdersByUserId方法
    2. 使用@Select註解
  2. 修改findUserById()方法,增加1對多延遲載入配置

介面

public interface UserMapper {

    /**
     通過id查詢1個使用者
     */
    @Select("select * from user where id=#{id}")
    @Results({
            @Result(column = "id", property = "id", id = true),  //主鍵對映
            // 一對一的配置
            @Result(column = "id", property = "userInfo",
                    //select表示要查詢的方法名 fetchType指定為LAZY表示延遲載入
                    one = @One(select = "findUserInfoById", fetchType = FetchType.LAZY)),
            //一對多的配置
            @Result(column = "id", property = "orders",
                    many = @Many(select = "findOrdersByUserId", fetchType = FetchType.LAZY))

    })
    User findUserById(int id);

    /**
     通過id查詢1個使用者擴充套件資訊,1對1
     */
    @Select("select * from user_info where id=#{id}")
    UserInfo findUserInfoById(int id);

    /**
     通過userId查詢這個使用者所有的訂單資訊,1對多
     */
    @Select("select * from order_form where user_id=#{id}")
    @Results({
            @Result(column = "user_id", property = "userId")
    })
    List<OrderForm> findOrdersByUserId(int userId);
}

小結

懶載入在不需要的時候就不去查詢,需要的時候就去查詢

17.學習總結

  1. Mybatis的入門配置
  2. Mybatis的CRUD
  3. Mybatis的關聯查詢
  4. 註解開發
  5. 註解關聯查詢