欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MyBatis 結(jié)果映射的幾種實現(xiàn)方式

 更新時間:2025年09月07日 09:51:17   作者:碼熔burning  
本文主要介紹了MyBatis中的結(jié)果映射機制,包括映射方式及其在處理關(guān)聯(lián)關(guān)系中的高級應(yīng)用,具有一定的參考價值,感興趣的可以了解一下

一、 什么是結(jié)果映射? ??

在我們的 Java 應(yīng)用程序中,數(shù)據(jù)通常以對象(JavaBeans/POJOs)的形式存在。然而,關(guān)系型數(shù)據(jù)庫是以行和列的形式存儲數(shù)據(jù)。當我們從數(shù)據(jù)庫查詢數(shù)據(jù)時,得到的是一個包含多行多列的結(jié)果集(ResultSet)。

結(jié)果映射(Result Mapping) 就是 MyBatis 中定義如何將數(shù)據(jù)庫查詢結(jié)果集中的列(Columns)映射到 Java 對象的屬性(Properties)上的規(guī)則和過程。它是解決數(shù)據(jù)庫中心的數(shù)據(jù)表示(表結(jié)構(gòu))與應(yīng)用程序中心的對象模型(類結(jié)構(gòu))之間“阻抗失配”問題的核心機制。

簡單來說: 告訴 MyBatis,數(shù)據(jù)庫查出來的 user_id 這一列的值,應(yīng)該賦給 User 這個 Java 類的 userId 這個屬性。

二、 為何需要結(jié)果映射? ??

  1. 命名差異:數(shù)據(jù)庫列名常用下劃線命名法(snake_case,如 order_id),而 Java 屬性常用駝峰命名法(camelCase,如 orderId)。需要轉(zhuǎn)換。
  2. 類型轉(zhuǎn)換 ??:數(shù)據(jù)庫類型(如 VARCHAR, TIMESTAMP, NUMBER)需要轉(zhuǎn)換為相應(yīng)的 Java 類型(如 String, java.util.Date, Integer, BigDecimal)。
  3. 復(fù)雜關(guān)系:實際應(yīng)用中,數(shù)據(jù)往往不是扁平的。一個對象可能包含另一個對象(一對一/多對一),或者包含一個對象集合(一對多)。需要機制來處理這些關(guān)聯(lián)。
  4. 顯式控制 ??:有時自動映射無法滿足需求,需要更精細地控制映射過程,例如列名和屬性名差異很大,或需要使用自定義的類型處理器(TypeHandler)。

三、 如何映射?(基礎(chǔ))?

MyBatis 提供了多種方式進行結(jié)果映射:

1、 別名映射 ??

這是最直接的方式,在 SQL 語句中使用 AS 關(guān)鍵字為查詢的列指定別名,讓別名與 Java 對象的屬性名完全一致。

Java Bean (User.java)

public class User {
    private Integer userId;
    private String userName;
    private String userEmail;
    // getters and setters...
}

Mapper XML (UserMapper.xml)

<select id="findUserById" resultType="com.yourcompany.domain.User">
  SELECT
      user_id   AS userId,  -- 使用 AS 將列名映射到屬性名
      user_name AS userName,
      email     AS userEmail -- 列名和屬性名不一致時必須用 AS
  FROM users
  WHERE user_id = #{id}
</select>
  • 優(yōu)點:非常明確,SQL 本身就定義了映射關(guān)系。
  • 缺點:SQL 語句會變得冗長,尤其當字段很多時。SQL 摻雜了部分映射邏輯。

2、 駝峰命名自動映射??

這是 MyBatis 提供的一個便捷功能。開啟后,MyBatis 會自動嘗試將下劃線命名法的列(column_name)映射到駝峰命名法的屬性(columnName)。

Java Bean (User.java) - 同上

Mapper XML (UserMapper.xml)

<select id="findUserById" resultType="com.yourcompany.domain.User">
  SELECT
      user_id,   -- 無需 AS
      user_name,
      email     -- 如果屬性名是 email,也能自動映射
  FROM users
  WHERE user_id = #{id}
</select>

(注意:如果 Java 屬性名不是標準的駝峰轉(zhuǎn)換,駝峰映射也無法自動處理)

如何開啟?

MyBatis 配置文件 (mybatis-config.xml):

<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

Spring Boot 配置文件 (application.propertiesapplication.yml):

# application.properties
mybatis.configuration.map-underscore-to-camel-case=true
# application.yml
mybatis:
  configuration:
    map-underscore-to-camel-case: true

通過 Java 配置 (如 Spring):

@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    // ... 其他配置
    org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
    configuration.setMapUnderscoreToCamelCase(true); // 開啟駝峰映射
    factoryBean.setConfiguration(configuration);
    // ... 其他配置
    return factoryBean.getObject();
}
  • 優(yōu)點:保持 SQL 簡潔 ?,配置一次全局生效,是目前推薦的主流簡單映射方式。
  • 缺點:需要配置開啟;對于非標準駝峰映射的場景無能為力。

3、 resultMap 顯式映射 ???

當自動映射(包括駝峰)無法滿足需求,或者需要處理復(fù)雜類型、關(guān)聯(lián)查詢時,resultMap 是最強大、最靈活的武器。它允許你顯式地、精確地定義列與屬性之間的映射關(guān)系。

Java Bean (User.java) - 同上

Mapper XML (UserMapper.xml)

定義 <resultMap>:

<resultMap id="userResultMap" type="com.yourcompany.domain.User">
    <!-- <id> 標簽用于映射主鍵字段,有助于 MyBatis 性能優(yōu)化 -->
    <id property="userId" column="user_id" />
    <!-- <result> 標簽用于映射普通字段 -->
    <result property="userName" column="user_name"/>
    <result property="userEmail" column="email"/>
    <!-- 可以指定 javaType 和 jdbcType,通常 MyBatis 能自動推斷 -->
    <!-- <result property="status" column="user_status" javaType="java.lang.Integer" jdbcType="INTEGER"/> -->
</resultMap>

<select> 標簽中使用 resultMap 屬性引用:

<select id="findUserById" resultMap="userResultMap">
  SELECT user_id, user_name, email FROM users WHERE user_id = #{id}
</select>
  • <resultMap> 屬性:

    • id: 在當前 Mapper XML 命名空間內(nèi)的唯一標識符。
    • type: 映射的目標 Java 類的完全限定名或 MyBatis 配置的別名。
  • 子標簽 <id><result> 屬性:

    • property: Java 對象的屬性名。
    • column: SQL 查詢結(jié)果集中的列名(或別名)。
    • javaType: Java 屬性的完整類名或別名(通??墒÷裕?/li>
    • jdbcType: 數(shù)據(jù)庫列的 JDBC 類型(枚舉 org.apache.ibatis.type.JdbcType)。
    • typeHandler: 指定自定義的類型處理器。
  • 優(yōu)點:控制力最強 ??!能處理各種復(fù)雜映射場景,是實現(xiàn)高級映射的基礎(chǔ)。代碼更清晰,SQL 保持純凈。

  • 缺點:配置相對繁瑣,增加了 XML 的代碼量。

四、 高級結(jié)果映射 (處理關(guān)聯(lián)關(guān)系) ??

當查詢結(jié)果需要映射到包含其他對象或?qū)ο蠹系膹?fù)雜 Java 對象時,就需要使用 resultMap 的高級特性:<association><collection>。

場景設(shè)定:

  • 實體類:
    • Department.java: 包含 id, name 屬性。
    • Employee.java: 包含 id, name, email, department (Department 對象), departmentId (Integer)。
  • 數(shù)據(jù)庫表:
    • departments (id PK, dept_name)
    • employees (id PK, emp_name, emp_email, dept_id FK references departments.id)

1、<association>(處理 “有一個” 關(guān)系 - To-One) ????

用于映射一個對象中包含的另一個對象,通常對應(yīng)數(shù)據(jù)庫中的 一對一多對一 關(guān)系。

兩種主要實現(xiàn)方式:

1. 嵌套 Select 查詢 (Nested Select)

  • 思路: 先查詢主對象(Employee),然后根據(jù)外鍵(dept_id),再執(zhí)行一個單獨的 SQL 查詢獲取關(guān)聯(lián)對象(Department)。
  • Mapper XML:
    <select id="findDepartmentById" resultType="com.yourcompany.domain.Department">...</select>
    
    <resultMap id="employeeWithDeptSelectMap" type="com.yourcompany.domain.Employee">
        <id property="id" column="id"/>
        <result property="name" column="emp_name"/>
        <!-- association: 映射 department 屬性 -->
        <association property="department" javaType="com.yourcompany.domain.Department"
                     column="dept_id"        select="findDepartmentById" />
                     <!-- column: 傳遞給 select 查詢的參數(shù)列 -->
                     <!-- select: 指定用于查詢關(guān)聯(lián)對象的 select 語句 ID -->
                     <!-- fetchType="lazy": 可配置懶加載 -->
    </resultMap>
    
    <select id="findEmployeeByIdWithDeptSelect" resultMap="employeeWithDeptSelectMap">...</select>
    
  • 優(yōu)點: 簡單直觀,SQL 語句分離,支持懶加載。
  • 缺點: N+1 查詢問題!性能可能很差 ??,通常不推薦使用 ?。

2. 嵌套結(jié)果映射 (Nested Result Map) ?

  • 思路: 使用 SQL 的 JOIN 操作一次性查詢出所有需要的數(shù)據(jù),然后在 resultMap 中定義嵌套結(jié)構(gòu)來映射連接后的結(jié)果。
  • Mapper XML:
    <resultMap id="employeeWithDeptNestedMap" type="com.yourcompany.domain.Employee">
        <id property="id" column="emp_id"/>
        <result property="name" column="emp_name"/>
        <result property="departmentId" column="dept_id"/>
    
        <!-- association: 映射 department 屬性 -->
        <association property="department" javaType="com.yourcompany.domain.Department">
            <!-- 嵌套定義 Department 的映射規(guī)則 -->
            <id property="id" column="dept_id"/>
            <result property="name" column="dept_name"/>
        </association>
    </resultMap>
    
    <select id="findEmployeeByIdWithDeptNested" resultMap="employeeWithDeptNestedMap">
        SELECT
            e.id AS emp_id, e.emp_name, e.emp_email, e.dept_id,
            d.id AS dept_id, d.dept_name -- 查詢關(guān)聯(lián)表的列,注意別名
        FROM employees e
        LEFT JOIN departments d ON e.dept_id = d.id
        WHERE e.id = #{empId}
    </select>
    
  • 優(yōu)點: 性能好 ??,只需執(zhí)行一次 SQL 查詢。結(jié)構(gòu)清晰。這是處理關(guān)聯(lián)關(guān)系推薦的方式 ?。
  • 缺點: SQL 語句可能因 JOIN 變得復(fù)雜;不支持懶加載(但通常性能好就不需要了)。

2、<collection>(處理 “有很多” 關(guān)系 - To-Many) ????

用于映射一個對象中包含的對象集合,通常對應(yīng)數(shù)據(jù)庫中的 一對多 關(guān)系。

同樣有兩種實現(xiàn)方式:

1. 嵌套 Select 查詢 (Nested Select)

  • 思路: 先查詢主對象(Department),然后根據(jù)主鍵(id),再執(zhí)行一個單獨的 SQL 查詢獲取關(guān)聯(lián)的對象集合(List)。
  • Java Bean (Department.java): (需要有 List<Employee> employees; 屬性)
  • Mapper XML:
    <select id="findEmployeesByDeptId" resultType="com.yourcompany.domain.Employee">...</select>
    
    <resultMap id="deptWithEmployeesSelectMap" type="com.yourcompany.domain.Department">
        <id property="id" column="id"/>
        <result property="name" column="dept_name"/>
        <!-- collection: 映射 employees 集合屬性 -->
        <collection property="employees" ofType="com.yourcompany.domain.Employee"
                    column="id"           select="findEmployeesByDeptId" />
                    <!-- column: 傳遞給 select 查詢的參數(shù)列 -->
                    <!-- select: 指定用于查詢關(guān)聯(lián)集合的 select 語句 ID -->
                    <!-- ofType: 指定集合中元素的類型 -->
                    <!-- fetchType="lazy": 支持懶加載 -->
    </resultMap>
    
    <select id="findDeptByIdWithEmployeesSelect" resultMap="deptWithEmployeesSelectMap">...</select>
    
  • 優(yōu)點: 簡單直觀,SQL 分離,支持懶加載。
  • 缺點: N+1 查詢問題!性能問題嚴重 ??,通常不推薦使用 ?。

2. 嵌套結(jié)果映射 (Nested Result Map) ?

  • 思路: 使用 SQL 的 LEFT JOIN 一次性查詢出部門及其所有員工的信息。MyBatis 的 resultMap 機制能智能地將重復(fù)的主對象信息合并,并將關(guān)聯(lián)的從對象信息收集到集合中。
  • Mapper XML:
    <resultMap id="employeeBaseMap" type="com.yourcompany.domain.Employee">...</resultMap>
    
    <resultMap id="deptWithEmployeesNestedMap" type="com.yourcompany.domain.Department">
        <id property="id" column="dept_id"/> <!-- 部門 ID 是主鍵 -->
        <result property="name" column="dept_name"/>
        <!-- collection: 映射 employees 集合屬性 -->
        <collection property="employees" ofType="com.yourcompany.domain.Employee"
                    resultMap="employeeBaseMap" />
                    <!-- ofType: 指定集合元素類型 -->
                    <!-- resultMap: 引用 Employee resultMap 來映射集合中的每個對象 -->
                    <!-- 或者可以直接在 collection 內(nèi)部定義映射規(guī)則 -->
    </resultMap>
    
    <select id="findDeptByIdWithEmployeesNested" resultMap="deptWithEmployeesNestedMap">
        SELECT
            d.id AS dept_id, d.dept_name,
            e.id AS emp_id, e.emp_name, e.emp_email
        FROM departments d
        LEFT JOIN employees e ON d.id = e.dept_id
        WHERE d.id = #{deptId}
    </select>
    
  • 優(yōu)點: 性能好 ??,只需一次 SQL 查詢。MyBatis 自動處理結(jié)果聚合。映射邏輯集中。這是處理一對多關(guān)系推薦的方式 ?。
  • 缺點: SQL 語句可能較復(fù)雜;返回的數(shù)據(jù)量可能較大(主表信息會重復(fù))。

五、 選擇哪種映射方式? ??

  • 簡單場景(列名與屬性名一致或符合駝峰規(guī)則):優(yōu)先使用駝峰自動映射 ??。
  • 列名與屬性名不一致/不規(guī)則:少數(shù)幾個字段用 SQL 別名 AS ??;較多或想保持 SQL 純凈,使用 resultMap ???。
  • 需要類型轉(zhuǎn)換/自定義 TypeHandler:必須使用 resultMap ??。
  • 處理一對一/多對一/一對多關(guān)聯(lián)關(guān)系:必須使用 resultMap<association><collection> ??。強烈推薦使用 嵌套結(jié)果映射 (Nested Result Map) 方式(基于 JOIN)?,避免 N+1 問題。只有在明確需要懶加載且能接受其潛在性能影響時,才考慮嵌套 Select。

六、 總結(jié) ??

MyBatis 的結(jié)果映射機制是其強大功能的核心之一。從簡單的別名、駝峰自動映射到強大的 resultMap(包括處理復(fù)雜關(guān)聯(lián)的 <association><collection>),它提供了靈活多樣的手段來連接數(shù)據(jù)庫表結(jié)構(gòu)和 Java 對象模型。理解并熟練運用這些映射方式,特別是掌握 resultMap 的高級用法并優(yōu)先選擇嵌套結(jié)果映射來處理關(guān)聯(lián),對于編寫高效、可維護的 MyBatis 應(yīng)用至關(guān)重要。

到此這篇關(guān)于MyBatis 結(jié)果映射的幾種實現(xiàn)方式的文章就介紹到這了,更多相關(guān)MyBatis 結(jié)果映射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java世界時區(qū)自動計算及時間生成方法詳解

    Java世界時區(qū)自動計算及時間生成方法詳解

    這篇文章主要為大家詳細介紹了Java中世界時區(qū)自動計算及時間生成的方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-12-12
  • 以Json形式的數(shù)據(jù)格式實現(xiàn)JMeter參數(shù)化

    以Json形式的數(shù)據(jù)格式實現(xiàn)JMeter參數(shù)化

    本文以小項目學院管理系統(tǒng)為例,給大家分享以Json形式的數(shù)據(jù)格式實現(xiàn)JMeter參數(shù)化的相關(guān)知識,包括添加元件操作步驟及使用用戶參數(shù)組件實現(xiàn)參數(shù)化的方法,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Javaweb監(jiān)聽器實例之統(tǒng)計在線人數(shù)

    Javaweb監(jiān)聽器實例之統(tǒng)計在線人數(shù)

    這篇文章主要為大家詳細介紹了Javaweb監(jiān)聽器實例之統(tǒng)計在線人數(shù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • mybatis如何使用truncate清空表

    mybatis如何使用truncate清空表

    這篇文章主要介紹了mybatis如何使用truncate清空表,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • springBoot啟動輸出三行日志控制臺自動停止操作

    springBoot啟動輸出三行日志控制臺自動停止操作

    這篇文章主要介紹了springBoot啟動輸出三行日志控制臺自動停止操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Spring中為bean指定InitMethod和DestroyMethod的執(zhí)行方法

    Spring中為bean指定InitMethod和DestroyMethod的執(zhí)行方法

    在Spring中,那些組成應(yīng)用程序的主體及由Spring IoC容器所管理的對象,被稱之為bean,接下來通過本文給大家介紹Spring中為bean指定InitMethod和DestroyMethod的執(zhí)行方法,感興趣的朋友一起看看吧
    2021-11-11
  • Java日期毫秒值和常見日期時間格式相互轉(zhuǎn)換方法

    Java日期毫秒值和常見日期時間格式相互轉(zhuǎn)換方法

    這篇文章主要給大家介紹了關(guān)于Java日期毫秒值和常見日期時間格式相互轉(zhuǎn)換的相關(guān)資料,在Java的日常開發(fā)中,會隨時遇到需要對時間處理的情況,文中給出了詳細的示例代碼,需要的朋友可以參考下
    2023-07-07
  • Java 繼承與多態(tài)的深入理解

    Java 繼承與多態(tài)的深入理解

    這篇文章主要介紹了Java 繼承與多態(tài)的深入理解的相關(guān)資料,子類繼承父類的特征和行為,使得子類具有父類的各種屬性和方法?;蜃宇悘母割惱^承方法,使得子類具有父類相同的行為,需要的朋友可以參考下
    2017-08-08
  • java中的異或問題代碼解析

    java中的異或問題代碼解析

    這篇文章主要介紹了java中的異或問題代碼解析,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Springboot整合Urule的方法步驟

    Springboot整合Urule的方法步驟

    這篇文章主要介紹了Springboot整合Urule的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05

最新評論