MyBatis 關於查詢語句上配置的詳細內容

Rainbow-Sea發表於2024-06-14

1. MyBatis 關於查詢語句上配置的詳細內容

@

目錄
  • 1. MyBatis 關於查詢語句上配置的詳細內容
  • 2. 準備工作
  • 3. SQL查詢結果,返回為POJO實體型別
  • 4. SQL查詢結果,返回為List<POJO> 集合型別
  • 5. SQL查詢結果,返回為Map 集合
  • 6. SQL查詢結果,返回為List<Map>集合
  • 7. SQL查詢結果,返回為Map<String,Map>
  • 8. SQL查詢結果,返回總記錄條數
  • 9. SQL查詢,resultMap 結果對映
    • 9.1 第二種方式:使用 resultMap 進行結果對映
    • 9.2 第三種方式:開啟駝峰命名自動對映
  • 10. 總結:
  • 11. 最後:


2. 準備工作

資料表結構的設計,資料表名為:t_car

在這裡插入圖片描述

t_car 表中的資料資訊:
在這裡插入圖片描述

pom.xml 檔案當中配置相關的依賴的 jar 包如下:

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>mybatis-005-crud-blog</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!--        mybatis 的依賴-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>

        <!--        mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

        <!--        引入 logback的依賴,這個日誌框架實現了slf4j 規範-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
    </dependencies>

</project>

配置 logback 的配置檔案,用於列印顯示,我們的日誌資訊,方便我們檢視我們的執行過程,效果。

在這裡插入圖片描述

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

<configuration debug="false">
    <!-- 控制檯輸出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化輸出:%d表示日期,%thread表示執行緒名,%-5level:級別從左顯示5個字元寬度%msg:日誌訊息,%n是換行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>

    <!-- 日誌輸出級別,logback日誌級別包括五個:TRACE < DEBUG < INFO < WARN < ERROR -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>

配置 MyBatis 的核心配置檔案,

在這裡插入圖片描述

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

        <!--  使用 <package>	還可以將這個包下的所有的類的全部自動起別名,別名就是簡名,不區分大小寫 -->
        <package name="com.rainbowsea.mybatis.pojo"/>
    </typeAliases>
    <environments default="mybatis">

        <environment id="mybatis">
            <!--            MANAGED 沒有用第三框架管理的話,都是會被提交的,沒有事務上的管理了 -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="MySQL123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 這裡也是可以使用 package 包名掃描,但是同樣的:對應介面路徑要一致,介面名一致-->
        <package name="com.rainbowsea.mybatis.mapper"></package>
    </mappers>
</configuration>

對照 t_car 建立的ORM 對映的 Car 類

注意:在MyBatis 當中對應的ORM ,一般在框架裡對應的 Bean實體類,一定要實現該 set 和 get 方法以及無引數構造方法,無法框架無法使用反射機制,進行操作

建議用包裝類,這樣可以防止 Null的問題,因為(簡單型別 int num = null ,是不可以賦值為 null)的編譯無法透過

在這裡插入圖片描述

package com.rainbowsea.mybatis.pojo;

public class Car {
    // 資料庫表當中的欄位應該和pojo類的屬性一一對應
    // 建議使用包裝類,這樣可以防止null的問題
    private Long id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private String produceTime;
    private String carType;

    public Car() {
    }

    public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {
        this.id = id;
        this.carNum = carNum;
        this.brand = brand;
        this.guidePrice = guidePrice;
        this.produceTime = produceTime;
        this.carType = carType;
    }

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", carNum='" + carNum + '\'' +
                ", brand='" + brand + '\'' +
                ", guidePrice=" + guidePrice +
                ", produceTime='" + produceTime + '\'' +
                ", catType='" + carType + '\'' +
                '}';
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCarNum() {
        return carNum;
    }

    public void setCarNum(String carNum) {
        this.carNum = carNum;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Double getGuidePrice() {
        return guidePrice;
    }

    public void setGuidePrice(Double guidePrice) {
        this.guidePrice = guidePrice;
    }

    public String getProduceTime() {
        return produceTime;
    }

    public void setProduceTime(String produceTime) {
        this.produceTime = produceTime;
    }

    public String getcarType() {
        return carType;
    }

    public void setcarType(String catType) {
        this.carType = catType;
    }
}

3. SQL查詢結果,返回為POJO實體型別

當查詢的結果,有對應的POJO 實體類,並且查詢結果只有一條時:

實操:

對應的介面

在這裡插入圖片描述

package com.rianbowsea.mybatis.mapper;


import com.rianbowsea.mybatis.pojo.Car;

public interface CarMapper {
    /**
     * 根據 id 查詢 Car 的值
     * @param id
     * @return
     */
    Car selectById(Long id);

}

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">

<!--    使用 as 別名,讓POJO實體類當中的屬性名與資料庫的查詢結果保持一致-->
    <select id="selectById" resultType="Car">
        SELECT id,
               car_num      as carNum,
               brand,
               guide_price  as guidePrice,
               produce_time as produceTime,
               car_type     as carType
        FROM `t_car`
        where id = #{id}
    </select>

</mapper>

執行測試:

查詢id為 118 的記錄結果:

在這裡插入圖片描述

package com.rainbowsea.mybatis.test;

import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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;

public class CarMapperTest {


    @Test
    public void testSelectById() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectById(118L);
        System.out.println(car);
    }
}

4. SQL查詢結果,返回為List<POJO> 集合型別

當查詢的記錄條數是多條的時候,必須使用集合接收。如果使用單個實體類接收會出現異常。

在這裡插入圖片描述

import com.rainbowsea.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {

    /**
     * 獲取所有的Car
     * @return
     */
    List<Car> selectAll();


}

注意:對於查詢結果返回多條記錄時,resultType的值是(集合/陣列儲存的元素的型別(除了Map集合是放Map集合本身))

在這裡插入圖片描述

<?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 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">

    <!--    使用 as 別名,讓POJO實體類當中的屬性名與資料庫的查詢結果保持一致-->
    <!--    注意:對於查詢結果返回多條記錄時,resultType的值是(集合/陣列儲存的元素的型別(除了Map集合是放Map集合本身))-->
    <select id="selectAll" resultType="Car">
        SELECT id,
               car_num      as carNum,
               brand,
               guide_price  as guidePrice,
               produce_time as produceTime,
               car_type     as carType
        FROM t_car
    </select>

</mapper>

執行測試:

查詢t_car 資料表中所有的記錄內容:

在這裡插入圖片描述

package com.rainbowsea.mybatis.test;

import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;

public class CarMapperTest {

    @Test
    public void testSelectAll() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectAll();

        cars.forEach(car -> {
            System.out.println(car);
        });

        sqlSession.close();
    }

}

如果返回多條記錄,採用單個實體類接收會怎樣 ?

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

查詢結果是一條的話可以使用List集合接收嗎?當然可以

就是List 集合當中,只會儲存一個記錄的內容POJO

5. SQL查詢結果,返回為Map 集合

當返回的資料,沒有合適的實體類POJO對應的時候,可以採用Map集合進行接受,欄位名做 : key ,欄位值做:value ,查詢結果可以保證只有一條資料,則返回一個Map集合。

注意:只有返回的是單個記錄的時候,才可以用單個Map集合儲存接受

Mybatis 在 查詢結果放到 Map 集合中存放的方式是:

     * Map<String,     Object>
     *      key          value
     *     "id"        	 131
     *     "car_num"      999
     *     "brand"     	 小米su7
     *     查詢資料庫中的欄位名          對於單個對應欄位的值

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

import com.rainbowsea.mybatis.pojo.Car;

import java.util.List;
import java.util.Map;

public interface CarMapper {
    /**
     *  Mybatis 在 查詢結果放到 Map 集合中存放的方式是:
     *  Map<String,     Object>
     *      k           v
     *     "id"         131
     *     "car_num"    999
     *     "brand"      小米su7
     *     查詢          對於單個對應欄位的值
     *     資料庫中
     *     的欄位名
     *
     *
     * @param id
     * @return
     */
    Map<String,Object> selectByIdRetMap(Long id);
}

注意:對於查詢結果返回多條記錄時,resultType的值是(集合/陣列儲存的元素的型別(除了Map集合是放Map集合本身))resultMap="map",這是因為mybatis內建了很多別名。【參見mybatis開發手冊】 https://mybatis.net.cn/

在這裡插入圖片描述

<?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 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">

    <!--    使用 as 別名,讓POJO實體類當中的屬性名與資料庫的查詢結果保持一致-->
    <!--    注意:對於查詢結果返回多條記錄時,resultType的值是(集合/陣列儲存的元素的型別(除了Map集合是放Map集合本身))-->
    <select id="selectByIdRetMap" resultType="Map">
        SELECT id,
               car_num      as carNum,
               brand,
               guide_price  as guidePrice,
               produce_time as produceTime,
               car_type     as carType
        FROM t_car
        where id = #{id}
    </select>
</mapper>

執行測試:

查詢 id 為 118 的記錄

在這裡插入圖片描述

package com.rainbowsea.mybatis.test;

import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;

public class CarMapperTest {

    @Test
    public void testSelectByIdRetMap() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Map<String, Object> cars = mapper.selectByIdRetMap(118L);
        System.out.println(cars);

        sqlSession.close();
    }

}

在這裡插入圖片描述

注意:只有返回的是單個記錄的時候,才可以用單個Map集合儲存接受 ,如果是多個記錄的話,

可以將Map集合放到List集合中。

反過來,如果返回的不是一條記錄,是多條記錄的話,只採用單個Map集合接收,這樣同樣會出現之前的異常:TooManyResultsException

在這裡插入圖片描述

6. SQL查詢結果,返回為List<Map>集合

查詢結果條數大於等於 1 條資料時,則可以返回一個儲存 Map 集合的 List 集合。List<Map> 等同於 List<Car>

在這裡插入圖片描述

在這裡插入圖片描述

注意: 這個 resultType 不是 List 是 map ,注意:除了單個特殊的 Map 集合的話(因為Map當中存在多個元素型別,無法斷定用其中的那個儲存的),其他的都是陣列/集合當中存放的資料的元素型別

在這裡插入圖片描述

<?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 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">

    <!--    使用 as 別名,讓POJO實體類當中的屬性名與資料庫的查詢結果保持一致-->
    <!--    這個 resultType 不是List 是 map ,注意:除了單個特殊的 Map -->
   <!--    這個 resultType 不是List 是 map ,注意:除了單個特殊的 Map 集合的話(因為Map當中存在多個元素型別,無法斷定用其中的那個儲存的),其他的都是陣列/集合當中存放的資料的元素型別-->
    <select id="selectAllRetListMap" resultType="map">
        SELECT id,
               car_num      as carNum,
               brand,
               guide_price  as guidePrice,
               produce_time as produceTime,
               car_type     as carType
        FROM `t_car` 
    </select>

</mapper>

測試執行程式:

在這裡插入圖片描述

package com.rainbowsea.mybatis.test;

import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;

public class CarMapperTest {


    @Test
    public void testSelectAllRetListMap() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Map<String, Object>> cars = mapper.selectAllRetListMap();
        cars.forEach(car->{
            System.out.println(car);
        });

        sqlSession.close();

    }

}

7. SQL查詢結果,返回為Map<String,Map>

這裡我們拿Car的id做 最外面的Map 的key,以後取出對應的Map集合時更方便。最外面裡面包含一個小Map集合

在這裡插入圖片描述

這裡我們需要使用 @MapKey 註解,該註解的作用就是將:將查詢結果的 id 欄位的值作為整個Map(最外面的那個Map)集合的key。

這裡你想將查詢結果中的那個欄位的值,賦值給“最外面的Map”集合的 key ,就填寫對應上的查詢上的欄位名即可

在這裡插入圖片描述

在這裡插入圖片描述

package com.rainbowsea.mybatis.mapper;


import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;

import java.util.List;
import java.util.Map;

public interface CarMapper {
    /**
     * 查詢所有的Car,返回一個Map集合
     * Map集合的key是每條記錄的主鍵值
     * Map集合的value是每條記錄
     * @return
     */
    @MapKey("id") // 將查詢結果的id欄位的值作為整個Map集合的key。
    Map<Long,Map<String,Object>> selectAllRetMap();

}

注意:我們這裡是一個Map中套裝一個Map,

Map集合比較特殊(存在兩個值:key,value) 所以要

繼續使用Map儲存查詢結果

在這裡插入圖片描述

<?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 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">

    <!--    使用 as 別名,讓POJO實體類當中的屬性名與資料庫的查詢結果保持一致-->
<!--    注意:這裡是用 Map集合進行接受的-->
    <select id="selectAllRetMap" resultType="Map">
        SELECT id,
               car_num      as carNum,
               brand,
               guide_price  as guidePrice,
               produce_time as produceTime,
               car_type     as carType
        FROM `t_car`
    </select>


</mapper>

執行測試:

查詢t_car 資料表中的所有內容。

在這裡插入圖片描述

在這裡插入圖片描述

package com.rainbowsea.mybatis.test;

import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;

public class CarMapperTest {

    @Test
    public void testSelectAllRetMap() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Map<Long,Map<String,Object>> cars = mapper.selectAllRetMap();
        System.out.println(cars);
        sqlSession.close();
    }

}

8. SQL查詢結果,返回總記錄條數

在這裡插入圖片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;

import java.util.List;
import java.util.Map;

public interface CarMapper {

    /**
     * 獲取Car的總記錄條數
     * @return
     */
    Long selectTotal();
}

需要注意的是: select count(具體某個欄位的話,是不會記錄null值的個數的),所以我們可以用 select count(1) from t_car ,恆為真的方式,查詢(這樣就包括了為 null 的值的個數了)

在這裡插入圖片描述

<?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 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">
    <!--    <select id="selectTotal" resultType="java.lang.Long"> ,也可以用別名-->
    <select id="selectTotal" resultType="Long">
        select count(1)
        from t_car
    </select>

</mapper>

執行測試:

查詢 t_car 資料表中的所有記錄條數。

在這裡插入圖片描述

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class CarMapperTest {

    @Test
    public void testSelectTotal() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Long count = mapper.selectTotal();
        System.out.println("總記錄條數" + count);
        sqlSession.close();

    }
}

9. SQL查詢,resultMap 結果對映

我們知道,要將 select 查詢的結果集儲存到對應的POJO實體類當中的必須要將查詢的欄位名和POJO實體類的屬性名兩者保持一致 ,但是我們的資料庫的命名規範是下劃線 ,而在Java當中的命名規範是駝峰命名 方式,兩者是不一致的。而想要將這兩者在不修改自身的屬性名字也能達到一個兩者名字保持一致的方案有 ,如下三種方式:

  1. 第一種方式:使用 AS 關鍵字給列起別名
  2. 第二種方式:使用 resultMap 進行結果對映
  3. 第三種方式:開啟MyBatis 的駝峰命名自動對映(配置 settings )

第一方式:我們上述的操作都是,使用的這種方式,下面就不多贅述了。

我們來學習一下,第二,三種方式。

9.1 第二種方式:使用 resultMap 進行結果對映

在這裡插入圖片描述



import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;

import java.util.List;
import java.util.Map;

public interface CarMapper {

    /**
     * 查詢所有的Car資訊,使用resultMap標籤進行結果對映
     * @return
     */
    List<Car> selectAllByResultMap();
}

resultMap 1.專門定義一個結果對映,在這個結果對映當中指定資料庫表的欄位名和Java類的屬性名的對應關係
type屬性,用來指定POJO類的類名
id屬性,指定resultMap的唯一標識,這個id將來要在select標籤中使用,啟用了別名機制, 也可以用別名

注意:resultMap屬性的值必須和resultMap標籤中id屬性值一致

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">

    <!--  resultMap  1.專門定義一個結果對映,在這個結果對映當中指定資料庫表的欄位名和Java類的屬性名的對應關係
            2.type屬性,用來指定POJO類的類名
            3.id屬性,指定resultMap的唯一標識,這個id將來要在select標籤中使用-->
    <!--    <resultMap id="carResultMap" type="com.rainbowsea.mybatis.pojo.Car">-->
    <!--  啟用了別名機制,  也可以用別名-->
    <resultMap id="carResultMap" type="Car">
        <!--        如果資料表中有主鍵,一般都是有主鍵的,要不然不符合資料庫設計第一正規化-->
        <!--        如果有主鍵,建議這裡配置一個id的標籤,注意:這不是必須的,但是官方的解釋是:這樣的配置可以讓mybatis 提高效率-->
        <id property="id" column="id"></id>
        <!--        property 後面填寫的值是:POJO類的屬性名-->
        <!--        column 後面填寫資料庫表查詢顯示的的欄位名(用了別名的話,是別名)-->
        <result property="carNum" column="car_num"></result>
        <!--當屬性名和資料庫列名一致時,可以省略。但建議都寫上。-->
        <!--javaType用來指定屬性型別。jdbcType用來指定列型別。一般可以省略。-->
        <result property="brand" column="brand" javaType="string" jdbcType="VARCHAR"/>
        <result property="guidePrice" column="guide_price"></result>
        <result property="produceTime" column="produce_time"></result>
        <result property="carType" column="car_type"></result>
    </resultMap>


    <!--    select標籤的resultMap的屬性,用來指定使用哪個結果對映,resultMap後面的值是resultMap的id-->
    <!--resultMap屬性的值必須和resultMap標籤中id屬性值一致。-->
    <select id="selectAllByResultMap" resultMap="carResultMap">
        SELECT id,
               car_num,
               brand,
               guide_price,
               produce_time,
               car_type
        FROM `t_car`
    </select>

</mapper>

執行測試:

查詢 t_car 資料表中的所有內容。

在這裡插入圖片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;

public class CarMapperTest {

    @Test
    public void testSelectAllByResultMap() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectAllByResultMap();
        cars.forEach(car -> {
            System.out.println(car);
        });

        sqlSession.close();
    }
}

9.2 第三種方式:開啟駝峰命名自動對映

使用這種方式的前提是:屬性名遵循Java駝峰 命名規範,資料庫表列名遵循SQL的下劃線 命名規範。

  • Java命名規範:首字母小寫,後面每個單詞首字母大寫,遵循駝峰命名方式
  • SQL命名規範:全部小寫,單詞之間採用下劃線分割

比如以下的對應關係:

比如以下的對應關係:

POJO 實體類中的屬性名 資料庫表的列名
carNum car_num
carType car_type
produceTime produce_time

如何啟用該功能,在 mybatis-config.xml 檔案中進行配置:

注意:setting 標籤方式的位置,可以根據錯誤提示進行修正位置。

在這裡插入圖片描述

<!--    mybatis 的全域性設定-->
    <settings>
<!--        是否開啟駝峰命名自動對映,即從經典資料庫列名 A_COLUMN 對映到經典 Java 屬性名 aColumn。 預設是 false 不開啟,true 表示開啟-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

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

<!--    mybatis 的全域性設定-->
    <settings>
<!--        是否開啟駝峰命名自動對映,即從經典資料庫列名 A_COLUMN 對映到經典 Java 屬性名 aColumn。 預設是 false 不開啟,true 表示開啟-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--    起別名-->
    <typeAliases>
        <!--  使用 <package>	還可以將這個包下的所有的類的全部自動起別名,別名就是簡名,不區分大小寫 -->
        <package name="com.rainbowsea.mybatis.pojo"/>
    </typeAliases>
    <environments default="mybatis">

        <environment id="mybatis">
            <!--            MANAGED 沒有用第三框架管理的話,都是會被提交的,沒有事務上的管理了 -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="MySQL123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 這裡也是可以使用 package 包名掃描,但是同樣的:對應介面路徑要一致,介面名一致-->
        <package name="com.rainbowsea.mybatis.mapper"></package>
    </mappers>
</configuration>

開啟後執行測試:

在這裡插入圖片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;

import java.util.List;
import java.util.Map;

public interface CarMapper {


    /**
     * mybatis 全域性設定,駝峰命名對映
     * @return
     */
    List<Car> selectAllByMapUnderscoreToCamelCase();

}

在這裡插入圖片描述

<?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 一定要是:對應的介面的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">
<!--    啟用了 mybatis 全域性設定,駝峰命名對映 -->
    <select id="selectAllByMapUnderscoreToCamelCase" resultType="Car">
        SELECT id,
               car_num,
               brand,
               guide_price,
               produce_time,
               car_type
        FROM `t_car`
    </select>

</mapper>

執行測試:

查詢 t_car 資料表的所有記錄

在這裡插入圖片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;

public class CarMapperTest {

    @Test
    public void testSelectAllByMapUnderscoreToCamelCase() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectAllByMapUnderscoreToCamelCase();
        cars.forEach(car -> {
            System.out.println(car);
        });

        sqlSession.close();
    }
}

10. 總結:

  1. 注意:對於查詢結果返回多條記錄時,resultType的值是(集合/陣列儲存的元素的型別(除了Map集合是放Map集合本身))

  2. 注意:只有返回的是單個記錄的時候,才可以用單個Map集合儲存接受 ,如果是多個記錄的話,可以將Map集合放到List集合中。反過來,如果返回的不是一條記錄,是多條記錄的話,只採用單個Map集合接收,這樣同樣會出現之前的異常:TooManyResultsException

  3. 這裡我們需要使用 @MapKey 註解,該註解的作用就是將:將查詢結果的 id 欄位的值作為整個Map(最外面的那個Map)集合的key。

     這裡你想將查詢結果中的那個欄位的值,賦值給“最外面的Map”集合的 key ,就填寫對應上的查詢上的欄位名即可
    
  4. resultMap 結果對映: 注意:resultMap屬性的值必須和resultMap標籤中id屬性值一致。property 後面填寫的值是:POJO類的屬性名;column 後面填寫資料庫表查詢顯示的的欄位名(用了別名的話,是別名)

  5. 開啟駝峰命名自動對映。屬性名遵循Java駝峰 命名規範,資料庫表列名遵循SQL的下劃線 命名規範。,同時注意:注意:setting 標籤方式的位置,可以根據錯誤提示進行修正位置。

  6. 如果查詢的結果是一個數值,則可以用數值型別進行接受。

11. 最後:

“在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。”

在這裡插入圖片描述

相關文章