最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis 配置復(fù)用從入門到精通

 更新時(shí)間:2026年03月07日 09:06:37   作者:雨夜  
本文將深入探討MyBatis的各種配置復(fù)用技巧,幫助您寫出更優(yōu)雅、更易維護(hù)的持久層代碼,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

MyBatis 配置復(fù)用詳解:從入門到精通

引言

在實(shí)際開發(fā)中,MyBatis 的 XML 配置文件往往會(huì)隨著業(yè)務(wù)復(fù)雜度提升而急劇膨脹。大量的重復(fù) SQL 和 resultMap 不僅難以維護(hù),還容易引入錯(cuò)誤。本文將深入探討 MyBatis 的各種配置復(fù)用技巧,幫助您寫出更優(yōu)雅、更易維護(hù)的持久層代碼。

一、SQL 片段復(fù)用

SQL 片段復(fù)用是最基礎(chǔ)也是最常用的復(fù)用方式,適用于重復(fù)的列名、查詢條件、排序分頁等場景。

1.1 基礎(chǔ) SQL 片段定義與引用

<mapper namespace="com.example.mapper.UserMapper">
    <!-- 定義常用列名片段 -->
    <sql id="Base_Column_List">
        id, username, password, email, phone, 
        status, create_time, update_time
    </sql>
    <!-- 定義查詢條件片段 -->
    <sql id="Where_Clause">
        <where>
            <if test="username != null and username != ''">
                AND username LIKE CONCAT('%', #{username}, '%')
            </if>
            <if test="email != null and email != ''">
                AND email = #{email}
            </if>
            <if test="status != null">
                AND status = #{status}
            </if>
            <if test="startTime != null">
                AND create_time >= #{startTime}
            </if>
            <if test="endTime != null">
                AND create_time <= #{endTime}
            </if>
        </where>
    </sql>
    <!-- 引用片段 -->
    <select id="selectByCondition" resultType="User">
        SELECT 
        <include refid="Base_Column_List"/>
        FROM user
        <include refid="Where_Clause"/>
    </select>
</mapper>

1.2 帶參數(shù)的 SQL 片段

SQL 片段支持參數(shù)傳遞,使其更加靈活:

<!-- 定義帶表別名的列片段 -->
<sql id="Alias_Columns">
    ${alias}.id, ${alias}.username, ${alias}.email, ${alias}.create_time
</sql>
<!-- 定義動(dòng)態(tài)表名片段 -->
<sql id="Dynamic_Table">
    ${tableName} ${alias}
</sql>
<!-- 定義連接條件片段 -->
<sql id="Join_Condition">
    ${mainAlias}.${mainField} = ${joinAlias}.${joinField}
</sql>
<!-- 使用參數(shù)化片段 -->
<select id="selectUserWithOrders" resultMap="UserOrderMap">
    SELECT
    <include refid="Alias_Columns">
        <property name="alias" value="u"/>
    </include>,
    o.id as order_id, o.order_no, o.amount
    FROM 
    <include refid="Dynamic_Table">
        <property name="tableName" value="user"/>
        <property name="alias" value="u"/>
    </include>
    LEFT JOIN order o ON 
    <include refid="Join_Condition">
        <property name="mainAlias" value="u"/>
        <property name="mainField" value="id"/>
        <property name="joinAlias" value="o"/>
        <property name="joinField" value="user_id"/>
    </include>
    WHERE u.id = #{id}
</select>

1.3 條件片段的高級(jí)用法

<!-- 定義多種條件片段 -->
<sql id="Basic_Conditions">
    <if test="deleted != null">
        AND deleted = #{deleted}
    </if>
    <if test="enabled != null">
        AND enabled = #{enabled}
    </if>
</sql>
<sql id="Time_Range_Condition">
    <if test="timeField != null and startTime != null">
        AND ${timeField} >= #{startTime}
    </if>
    <if test="timeField != null and endTime != null">
        AND ${timeField} <= #{endTime}
    </if>
</sql>
<sql id="Pagination">
    <if test="offset != null and limit != null">
        LIMIT #{offset}, #{limit}
    </if>
    <if test="pageNum != null and pageSize != null">
        LIMIT #{pageNum}, #{pageSize}
    </if>
</sql>
<!-- 組合使用 -->
<select id="searchUsers" resultType="User">
    SELECT * FROM user
    <where>
        <include refid="Basic_Conditions"/>
        <include refid="Time_Range_Condition">
            <property name="timeField" value="create_time"/>
        </include>
        <if test="keyword != null">
            AND (username LIKE CONCAT('%', #{keyword}, '%')
                 OR email LIKE CONCAT('%', #{keyword}, '%'))
        </if>
    </where>
    ORDER BY create_time DESC
    <include refid="Pagination"/>
</select>

1.4 SQL 片段的嵌套使用

<!-- 定義基礎(chǔ)片段 -->
<sql id="User_Fields">
    id, username, email
</sql>
<sql id="User_Base_Query">
    SELECT <include refid="User_Fields"/> FROM user
</sql>
<!-- 嵌套構(gòu)建復(fù)雜查詢 -->
<sql id="Active_User_Query">
    <include refid="User_Base_Query"/>
    WHERE status = 1 AND last_login_time > DATE_SUB(NOW(), INTERVAL 30 DAY)
</sql>
<sql id="Vip_User_Query">
    <include refid="User_Base_Query"/>
    WHERE vip_level > 0
</sql>
<!-- 使用 -->
<select id="countActiveVipUsers" resultType="int">
    SELECT COUNT(*) FROM (
        <include refid="Active_User_Query"/>
        UNION
        <include refid="Vip_User_Query"/>
    ) AS combined
</select>

二、resultMap 復(fù)用

resultMap 復(fù)用是處理復(fù)雜對(duì)象映射的關(guān)鍵技術(shù),可以避免重復(fù)定義字段映射關(guān)系。

2.1 基礎(chǔ)繼承復(fù)用

<!-- 基礎(chǔ)映射定義 -->
<resultMap id="BaseResultMap" type="com.example.entity.User">
    <id property="id" column="id" jdbcType="BIGINT"/>
    <result property="username" column="username" jdbcType="VARCHAR"/>
    <result property="password" column="password" jdbcType="VARCHAR"/>
    <result property="email" column="email" jdbcType="VARCHAR"/>
    <result property="phone" column="phone" jdbcType="VARCHAR"/>
    <result property="status" column="status" jdbcType="INTEGER"/>
    <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
    <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- 繼承并擴(kuò)展關(guān)聯(lián)對(duì)象 -->
<resultMap id="UserWithRoleMap" extends="BaseResultMap" type="com.example.entity.User">
    <!-- 一對(duì)一關(guān)聯(lián) -->
    <association property="role" javaType="com.example.entity.Role">
        <id property="id" column="role_id"/>
        <result property="name" column="role_name"/>
        <result property="code" column="role_code"/>
        <result property="description" column="role_desc"/>
    </association>
</resultMap>
<!-- 繼承并擴(kuò)展集合對(duì)象 -->
<resultMap id="UserWithOrdersMap" extends="BaseResultMap" type="com.example.entity.User">
    <!-- 一對(duì)多集合 -->
    <collection property="orders" ofType="com.example.entity.Order" 
                notNullColumn="order_id">
        <id property="id" column="order_id"/>
        <result property="orderNo" column="order_no"/>
        <result property="amount" column="amount"/>
        <result property="status" column="order_status"/>
        <result property="createTime" column="order_create_time"/>
    </collection>
</resultMap>
<!-- 多層繼承 -->
<resultMap id="UserFullInfoMap" extends="UserWithRoleMap" type="com.example.entity.User">
    <collection property="permissions" ofType="com.example.entity.Permission">
        <id property="id" column="permission_id"/>
        <result property="name" column="permission_name"/>
        <result property="code" column="permission_code"/>
    </collection>
    <!-- 添加額外屬性 -->
    <result property="lastLoginIp" column="last_login_ip"/>
    <result property="lastLoginTime" column="last_login_time"/>
</resultMap>

2.2 引用外部 resultMap

<!-- 定義可復(fù)用的關(guān)聯(lián)映射(可在其他文件中) -->
<mapper namespace="com.example.mapper.RoleMapper">
    <resultMap id="RoleMap" type="com.example.entity.Role">
        <id property="id" column="role_id"/>
        <result property="name" column="role_name"/>
        <result property="code" column="role_code"/>
        <result property="permissions" column="id" 
                select="com.example.mapper.PermissionMapper.selectByRoleId"/>
    </resultMap>
</mapper>
<!-- 在當(dāng)前文件中引用 -->
<mapper namespace="com.example.mapper.UserMapper">
    <resultMap id="UserWithRoleRefMap" extends="BaseResultMap" 
               type="com.example.entity.User">
        <!-- 引用外部 resultMap,注意列別名要匹配 -->
        <association property="role" 
                     resultMap="com.example.mapper.RoleMapper.RoleMap"
                     columnPrefix="role_"/>
        <!-- 也可以使用 select 方式引用 -->
        <collection property="roles" 
                    column="id" 
                    select="com.example.mapper.RoleMapper.selectByUserId"/>
    </resultMap>
    <!-- 對(duì)應(yīng)的查詢 -->
    <select id="selectUserWithRole" resultMap="UserWithRoleRefMap">
        SELECT 
            u.*,
            r.id as role_id,
            r.name as role_name,
            r.code as role_code
        FROM user u
        LEFT JOIN user_role ur ON u.id = ur.user_id
        LEFT JOIN role r ON ur.role_id = r.id
        WHERE u.id = #{id}
    </select>
</mapper>

2.3 使用 columnPrefix 實(shí)現(xiàn)同一結(jié)構(gòu)的復(fù)用

<!-- 定義地址映射 -->
<resultMap id="AddressMap" type="com.example.entity.Address">
    <result property="province" column="province"/>
    <result property="city" column="city"/>
    <result property="district" column="district"/>
    <result property="street" column="street"/>
    <result property="detail" column="detail"/>
    <result property="zipCode" column="zip_code"/>
</resultMap>
<!-- 在多個(gè)地方復(fù)用,通過 columnPrefix 區(qū)分不同地址 -->
<resultMap id="UserWithAddressesMap" type="com.example.entity.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <!-- 注冊(cè)地址,使用 reg_ 前綴 -->
    <association property="registerAddress" 
                 resultMap="AddressMap" 
                 columnPrefix="reg_"/>
    <!-- 居住地址,使用 live_ 前綴 -->
    <association property="livingAddress" 
                 resultMap="AddressMap" 
                 columnPrefix="live_"/>
    <!-- 工作地址,使用 work_ 前綴 -->
    <association property="workAddress" 
                 resultMap="AddressMap" 
                 columnPrefix="work_"/>
    <!-- 收貨地址列表,每個(gè)地址使用不同的前綴 -->
    <collection property="shippingAddresses" 
                ofType="com.example.entity.Address"
                resultMap="AddressMap"
                columnPrefix="ship_"/>
</resultMap>
<!-- 對(duì)應(yīng)的查詢 -->
<select id="selectUserWithAllAddresses" resultMap="UserWithAddressesMap">
    SELECT 
        u.id, u.username,
        ra.province as reg_province,
        ra.city as reg_city,
        ra.district as reg_district,
        ra.street as reg_street,
        ra.detail as reg_detail,
        ra.zip_code as reg_zip_code,
        la.province as live_province,
        la.city as live_city,
        la.district as live_district,
        la.street as live_street,
        la.detail as live_detail,
        la.zip_code as live_zip_code,
        wa.province as work_province,
        wa.city as work_city,
        wa.district as work_district,
        wa.street as work_street,
        wa.detail as work_detail,
        wa.zip_code as work_zip_code,
        sa.province as ship_province,
        sa.city as ship_city,
        sa.district as ship_district,
        sa.street as ship_street,
        sa.detail as ship_detail,
        sa.zip_code as ship_zip_code
    FROM user u
    LEFT JOIN address ra ON u.register_address_id = ra.id
    LEFT JOIN address la ON u.living_address_id = la.id
    LEFT JOIN address wa ON u.work_address_id = wa.id
    LEFT JOIN user_shipping_address usa ON u.id = usa.user_id
    LEFT JOIN address sa ON usa.address_id = sa.id
    WHERE u.id = #{id}
</select>

2.4 構(gòu)造方法映射復(fù)用

<!-- 定義帶構(gòu)造方法的映射 -->
<resultMap id="ConstructorMap" type="com.example.entity.User">
    <constructor>
        <idArg column="id" javaType="Long"/>
        <arg column="username" javaType="String"/>
        <arg column="email" javaType="String"/>
        <arg column="create_time" javaType="java.time.LocalDateTime"/>
    </constructor>
</resultMap>
<!-- 繼承構(gòu)造方法映射 -->
<resultMap id="UserWithRoleConstructorMap" extends="ConstructorMap" 
           type="com.example.entity.User">
    <association property="role" javaType="com.example.entity.Role">
        <id property="id" column="role_id"/>
        <result property="name" column="role_name"/>
    </association>
</resultMap>
<!-- 使用不同的構(gòu)造參數(shù)順序 -->
<resultMap id="AlternativeConstructorMap" type="com.example.entity.User">
    <constructor>
        <arg column="username" javaType="String"/>
        <arg column="email" javaType="String"/>
        <idArg column="id" javaType="Long"/>
    </constructor>
</resultMap>

2.5 鑒別器映射復(fù)用

<!-- 定義基礎(chǔ)映射 -->
<resultMap id="BaseMessageMap" type="com.example.entity.Message">
    <id property="id" column="id"/>
    <result property="content" column="content"/>
    <result property="createTime" column="create_time"/>
</resultMap>
<!-- 使用鑒別器實(shí)現(xiàn)多態(tài)查詢 -->
<resultMap id="MessageMap" extends="BaseMessageMap" 
           type="com.example.entity.Message">
    <discriminator javaType="int" column="message_type">
        <!-- 文本消息 -->
        <case value="1" resultMap="TextMessageMap"/>
        <!-- 圖片消息 -->
        <case value="2" resultMap="ImageMessageMap"/>
        <!-- 語音消息 -->
        <case value="3" resultMap="VoiceMessageMap"/>
        <!-- 視頻消息,繼承基礎(chǔ)映射并擴(kuò)展 -->
        <case value="4" resultType="com.example.entity.VideoMessage">
            <result property="videoUrl" column="video_url"/>
            <result property="duration" column="duration"/>
            <result property="thumbnail" column="thumbnail"/>
        </case>
    </discriminator>
</resultMap>
<!-- 各子類映射可以繼續(xù)繼承 -->
<resultMap id="TextMessageMap" extends="BaseMessageMap" 
           type="com.example.entity.TextMessage">
    <result property="textFormat" column="text_format"/>
</resultMap>
<resultMap id="ImageMessageMap" extends="BaseMessageMap" 
           type="com.example.entity.ImageMessage">
    <result property="imageUrl" column="image_url"/>
    <result property="width" column="width"/>
    <result property="height" column="height"/>
</resultMap>

三、高級(jí)復(fù)用技巧

3.1 通過繼承復(fù)用完整查詢

<!-- 基礎(chǔ)查詢 -->
<select id="selectBaseUsers" resultMap="BaseResultMap">
    SELECT id, username, email, status 
    FROM user 
    WHERE status = 1
</select>
<!-- 繼承基礎(chǔ)查詢并擴(kuò)展條件 -->
<select id="selectActiveUsers" resultMap="BaseResultMap" 
        extends="selectBaseUsers">
    AND last_login_time > #{lastLoginTime}
</select>
<!-- 繼承并修改排序 -->
<select id="selectRecentActiveUsers" resultMap="BaseResultMap" 
        extends="selectActiveUsers">
    ORDER BY last_login_time DESC
    LIMIT #{limit}
</select>
<!-- 多層繼承 -->
<select id="selectVipActiveUsers" resultMap="UserWithRoleMap" 
        extends="selectActiveUsers">
    AND vip_level > 0
    AND EXISTS (SELECT 1 FROM user_role WHERE user_id = user.id)
</select>

3.2 泛型基礎(chǔ)映射抽象

<!-- 定義抽象的基礎(chǔ)映射(不指定具體類型) -->
<resultMap id="BaseEntityMap" type="com.example.entity.BaseEntity">
    <id property="id" column="id"/>
    <result property="createTime" column="create_time"/>
    <result property="updateTime" column="update_time"/>
    <result property="createBy" column="create_by"/>
    <result property="updateBy" column="update_by"/>
    <result property="deleted" column="deleted" javaType="boolean"/>
</resultMap>
<!-- 子類繼承基礎(chǔ)映射 -->
<resultMap id="ProductMap" extends="BaseEntityMap" 
           type="com.example.entity.Product">
    <result property="name" column="name"/>
    <result property="price" column="price"/>
    <result property="stock" column="stock"/>
</resultMap>
<resultMap id="OrderMap" extends="BaseEntityMap" 
           type="com.example.entity.Order">
    <result property="orderNo" column="order_no"/>
    <result property="amount" column="amount"/>
    <result property="userId" column="user_id"/>
</resultMap>
<resultMap id="CategoryMap" extends="BaseEntityMap" 
           type="com.example.entity.Category">
    <result property="name" column="name"/>
    <result property="parentId" column="parent_id"/>
    <result property="level" column="level"/>
</resultMap>

3.3 動(dòng)態(tài)映射組合

<!-- 定義可選的映射片段 -->
<sql id="Optional_User_Fields">
    <if test="includeProfile">
        , profile, avatar
    </if>
    <if test="includeStats">
        , login_count, last_login_ip
    </if>
</sql>
<!-- 動(dòng)態(tài)構(gòu)建 resultMap 的引用 -->
<resultMap id="DynamicUserMap" type="com.example.entity.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <!-- 基礎(chǔ)字段始終包含 -->
</resultMap>
<resultMap id="UserWithProfileMap" extends="DynamicUserMap" 
           type="com.example.entity.User">
    <result property="profile" column="profile"/>
    <result property="avatar" column="avatar"/>
</resultMap>
<resultMap id="UserWithStatsMap" extends="DynamicUserMap" 
           type="com.example.entity.User">
    <result property="loginCount" column="login_count"/>
    <result property="lastLoginIp" column="last_login_ip"/>
</resultMap>
<!-- 根據(jù)條件動(dòng)態(tài)選擇 resultMap -->
<select id="selectUserDynamic" resultMap="DynamicUserMap">
    SELECT id, username
    <include refid="Optional_User_Fields"/>
    FROM user
    WHERE id = #{id}
</select>

3.4 類型處理器復(fù)用

<!-- 自定義類型處理器 -->
<typeHandler handler="com.example.handler.JsonTypeHandler" 
             javaType="com.example.entity.JsonObject"/>
<typeHandler handler="com.example.handler.EnumTypeHandler" 
             javaType="com.example.enums.StatusEnum"/>
<!-- 在 resultMap 中復(fù)用 -->
<resultMap id="ProductDetailMap" type="com.example.entity.Product">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <!-- 復(fù)用 JSON 處理器 -->
    <result property="attributes" column="attributes" 
            typeHandler="com.example.handler.JsonTypeHandler"/>
    <result property="specs" column="specs" 
            typeHandler="com.example.handler.JsonTypeHandler"/>
    <!-- 復(fù)用枚舉處理器 -->
    <result property="status" column="status" 
            typeHandler="com.example.handler.EnumTypeHandler"/>
    <result property="category" column="category" 
            typeHandler="com.example.handler.EnumTypeHandler"/>
</resultMap>
<!-- 在多個(gè)映射中復(fù)用相同的處理器配置 -->
<resultMap id="OrderExtrasMap" type="com.example.entity.Order">
    <result property="extras" column="extras" 
            typeHandler="com.example.handler.JsonTypeHandler"/>
    <result property="status" column="status" 
            typeHandler="com.example.handler.EnumTypeHandler"/>
</resultMap>

四、最佳實(shí)踐與注意事項(xiàng)

4.1 命名規(guī)范建議

<!-- 使用清晰、一致的命名規(guī)范 -->
<mapper namespace="com.example.mapper.UserMapper">
    <!-- SQL 片段命名:功能 + 類型 -->
    <sql id="Base_Column_List"/>           <!-- 基礎(chǔ)列名 -->
    <sql id="Base_Where_Clause"/>           <!-- 基礎(chǔ)條件 -->
    <sql id="Refined_Where_Clause"/>        <!-- 精確條件 -->
    <sql id="Fuzzy_Where_Clause"/>          <!-- 模糊條件 -->
    <sql id="Order_By_Clause"/>             <!-- 排序 -->
    <sql id="Pagination_Clause"/>           <!-- 分頁 -->
    <!-- resultMap 命名:實(shí)體 + 功能 + Map -->
    <resultMap id="BaseResultMap"/>         <!-- 基礎(chǔ)映射 -->
    <resultMap id="UserWithRoleMap"/>       <!-- 帶角色 -->
    <resultMap id="UserDetailMap"/>         <!-- 詳細(xì)信息 -->
    <resultMap id="UserLazyMap"/>           <!-- 懶加載 -->
    <!-- 查詢命名:操作 + 條件 + 結(jié)果類型 -->
    <select id="selectById"/>
    <select id="selectByCondition"/>
    <select id="selectWithRoleById"/>
    <select id="selectPage"/>
</mapper>

4.2 性能考慮

<!-- 1. 懶加載配置 -->
<resultMap id="UserLazyMap" type="com.example.entity.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <!-- 設(shè)置懶加載 -->
    <association property="role" 
                 select="com.example.mapper.RoleMapper.selectByUserId"
                 column="id"
                 fetchType="lazy"/>
    <collection property="orders"
                select="com.example.mapper.OrderMapper.selectByUserId"
                column="id"
                fetchType="lazy"/>
</resultMap>
<!-- 2. 使用延遲加載的全局配置 -->
<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
    <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
<!-- 3. 批量查詢優(yōu)化 -->
<resultMap id="UserWithOrdersBatchMap" type="com.example.entity.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <!-- 使用批量查詢 -->
    <collection property="orders" 
                ofType="com.example.entity.Order"
                select="com.example.mapper.OrderMapper.selectByUserIds"
                column="{userIds=id}"/>
</resultMap>

4.3 常見問題與解決方案

<!-- 問題1:循環(huán)引用導(dǎo)致棧溢出 -->
<!-- 解決方案:合理設(shè)置遞歸深度或使用延遲加載 -->
<resultMap id="CategoryTreeMap" type="com.example.entity.Category">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <!-- 設(shè)置遞歸查詢,但要有終止條件 -->
    <collection property="children" 
                ofType="com.example.entity.Category"
                select="selectChildren"
                column="{parentId=id, level=level+1}"/>
</resultMap>
<!-- 問題2:字段沖突 -->
<!-- 解決方案:使用別名和 columnPrefix -->
<resultMap id="UserProductMap" type="com.example.entity.UserProduct">
    <id property="userId" column="user_id"/>
    <id property="productId" column="product_id"/>
    <!-- 使用別名區(qū)分同名字段 -->
    <association property="user" resultMap="UserMap" columnPrefix="u_"/>
    <association property="product" resultMap="ProductMap" columnPrefix="p_"/>
</resultMap>
<!-- 問題3:N+1 查詢問題 -->
<!-- 解決方案:使用聯(lián)表查詢代替嵌套查詢 -->
<resultMap id="UserWithOrdersJoinMap" type="com.example.entity.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <!-- 使用聯(lián)表查詢 -->
    <collection property="orders" ofType="com.example.entity.Order">
        <id property="id" column="order_id"/>
        <result property="orderNo" column="order_no"/>
        <result property="amount" column="amount"/>
    </collection>
</resultMap>
<!-- 對(duì)應(yīng)的優(yōu)化查詢 -->
<select id="selectUserWithOrders" resultMap="UserWithOrdersJoinMap">
    SELECT 
        u.*,
        o.id as order_id,
        o.order_no,
        o.amount
    FROM user u
    LEFT JOIN order o ON u.id = o.user_id
    WHERE u.id = #{id}
</select>

五、實(shí)際項(xiàng)目應(yīng)用示例

5.1 通用 CRUD 復(fù)用框架

<!-- BaseMapper.xml - 基礎(chǔ)映射文件 -->
<mapper namespace="com.example.mapper.BaseMapper">
    <!-- 通用字段 -->
    <sql id="Base_Column">
        id, create_time, update_time, create_by, update_by, deleted
    </sql>
    <!-- 通用條件:未刪除 -->
    <sql id="Not_Deleted">
        AND deleted = 0
    </sql>
    <!-- 通用 resultMap -->
    <resultMap id="BaseResultMap" type="com.example.entity.BaseEntity">
        <id property="id" column="id"/>
        <result property="createTime" column="create_time"/>
        <result property="updateTime" column="update_time"/>
        <result property="createBy" column="create_by"/>
        <result property="updateBy" column="update_by"/>
        <result property="deleted" column="deleted"/>
    </resultMap>
    <!-- 通用插入 -->
    <sql id="Base_Insert">
        INSERT INTO ${tableName} (
            <include refid="Base_Column"/>
            <if test="extraFields != null">
                , ${extraFields}
            </if>
        ) VALUES (
            #{id}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleted}
            <if test="extraValues != null">
                , ${extraValues}
            </if>
        )
    </sql>
    <!-- 通用更新 -->
    <sql id="Base_Update">
        UPDATE ${tableName}
        <set>
            update_time = NOW(),
            <if test="updateBy != null">update_by = #{updateBy},</if>
            ${updateFields}
        </set>
        WHERE id = #{id}
    </sql>
</mapper>
<!-- UserMapper.xml - 具體實(shí)現(xiàn) -->
<mapper namespace="com.example.mapper.UserMapper">
    <!-- 繼承通用 resultMap -->
    <resultMap id="UserMap" extends="com.example.mapper.BaseMapper.BaseResultMap" 
               type="com.example.entity.User">
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="email" column="email"/>
        <result property="phone" column="phone"/>
        <result property="status" column="status"/>
    </resultMap>
    <!-- 使用通用 SQL 片段 -->
    <select id="selectById" resultMap="UserMap">
        SELECT 
            <include refid="com.example.mapper.BaseMapper.Base_Column"/>,
            username, password, email, phone, status
        FROM user
        WHERE id = #{id}
        <include refid="com.example.mapper.BaseMapper.Not_Deleted"/>
    </select>
    <!-- 復(fù)雜查詢 -->
    <select id="selectUserDetail" resultMap="UserDetailMap">
        SELECT 
            u.*,
            r.id as role_id,
            r.name as role_name,
            r.code as role_code,
            d.id as dept_id,
            d.name as dept_name
        FROM user u
        LEFT JOIN user_role ur ON u.id = ur.user_id
        LEFT JOIN role r ON ur.role_id = r.id
        LEFT JOIN department d ON u.dept_id = d.id
        WHERE u.id = #{id}
        <include refid="com.example.mapper.BaseMapper.Not_Deleted"/>
    </select>
</mapper>

5.2 多租戶系統(tǒng)復(fù)用

<!-- 租戶隔離的基礎(chǔ)配置 -->
<mapper namespace="com.example.mapper.TenantBaseMapper">
    <!-- 租戶字段 -->
    <sql id="Tenant_Column">
        tenant_id
    </sql>
    <!-- 租戶條件 -->
    <sql id="Tenant_Condition">
        AND tenant_id = #{tenantId}
    </sql>
    <!-- 自動(dòng)注入租戶ID -->
    <sql id="Auto_Set_Tenant">
        <if test="tenantId == null">
            #{_parameter.getTenantId()} as tenant_id,
        </if>
        <if test="tenantId != null">
            #{tenantId} as tenant_id,
        </if>
    </sql>
    <!-- 租戶基礎(chǔ) resultMap -->
    <resultMap id="TenantBaseMap" extends="com.example.mapper.BaseMapper.BaseResultMap">
        <result property="tenantId" column="tenant_id"/>
    </resultMap>
</mapper>
<!-- 業(yè)務(wù)表繼承租戶配置 -->
<resultMap id="BusinessMap" extends="com.example.mapper.TenantBaseMapper.TenantBaseMap" 
           type="com.example.entity.Business">
    <!-- 業(yè)務(wù)特有字段 -->
    <result property="name" column="name"/>
    <result property="code" column="code"/>
</resultMap>
<!-- 查詢時(shí)自動(dòng)帶上租戶條件 -->
<select id="selectByBusiness" resultMap="BusinessMap">
    SELECT * FROM business
    <where>
        <include refid="com.example.mapper.TenantBaseMapper.Tenant_Condition"/>
        <if test="name != null">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
    </where>
</select>

六、總結(jié)

6.1 復(fù)用方式對(duì)比

復(fù)用方式適用場景優(yōu)點(diǎn)缺點(diǎn)
SQL 片段重復(fù)的 SQL 代碼塊簡單直觀,參數(shù)靈活僅限于 SQL 層面
resultMap 繼承實(shí)體映射復(fù)用面向?qū)ο螅С侄鄳B(tài)繼承層級(jí)過深難維護(hù)
columnPrefix同一結(jié)構(gòu)多字段避免重復(fù)定義查詢語句較復(fù)雜
引用外部 resultMap跨文件復(fù)用模塊化好,解耦需注意命名空間
查詢繼承相似查詢復(fù)用減少重復(fù) SQL調(diào)試相對(duì)困難

6.2 最佳實(shí)踐建議

  1. 合理粒度:SQL 片段粒度不宜過細(xì),避免過度拆分
  2. 命名規(guī)范:建立統(tǒng)一的命名規(guī)范,提高可讀性
  3. 適度繼承:resultMap 繼承層級(jí)建議不超過 3 層
  4. 性能考慮:注意 N+1 問題,合理使用聯(lián)表查詢
  5. 注釋完善:關(guān)鍵復(fù)用點(diǎn)添加注釋,說明用途和使用方式
  6. 版本控制:復(fù)用配置變更時(shí)注意影響范圍

6.3 注意事項(xiàng)

  • 作用域:同 namespace 內(nèi)可直接引用,跨 namespace 需使用全限定名
  • 參數(shù)傳遞<include> 標(biāo)簽的 <property> 只在當(dāng)前片段有效
  • 優(yōu)先級(jí):extends 的 SQL 會(huì)在當(dāng)前 SQL 之前執(zhí)行
  • 循環(huán)依賴:避免 resultMap 循環(huán)引用導(dǎo)致棧溢出
  • 調(diào)試難度:過度復(fù)用可能增加調(diào)試難度,需要權(quán)衡

通過合理運(yùn)用這些復(fù)用技巧,可以顯著提高 MyBatis 配置的可維護(hù)性,減少重復(fù)代碼,提升開發(fā)效率。在實(shí)際項(xiàng)目中,建議根據(jù)具體場景選擇合適的復(fù)用方式,并建立團(tuán)隊(duì)統(tǒng)一的規(guī)范。

到此這篇關(guān)于MyBatis 配置復(fù)用從入門到精通的文章就介紹到這了,更多相關(guān)mybatis 配置復(fù)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot整合thymleaf模板引擎過程解析

    Springboot整合thymleaf模板引擎過程解析

    這篇文章主要介紹了Springboot整合thymleaf模板引擎過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot系列教程之防重放與操作冪等

    SpringBoot系列教程之防重放與操作冪等

    同一條數(shù)據(jù)被用戶點(diǎn)擊了多次,導(dǎo)致數(shù)據(jù)冗余,需要防止弱網(wǎng)絡(luò)等環(huán)境下的重復(fù)點(diǎn)擊,下面這篇文章主要給大家介紹了關(guān)于SpringBoot系列教程之防重放與操作冪等的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • SpringBoot?緩存預(yù)熱的實(shí)現(xiàn)

    SpringBoot?緩存預(yù)熱的實(shí)現(xiàn)

    本文主要介紹了SpringBoot?緩存預(yù)熱的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2007-11-11
  • Java實(shí)現(xiàn)Excel表單控件的添加與刪除

    Java實(shí)現(xiàn)Excel表單控件的添加與刪除

    本文通過Java代碼示例介紹如何在Excel表格中添加表單控件,包括文本框、單選按鈕、復(fù)選框、組合框、微調(diào)按鈕等,以及如何刪除Excel中的指定表單控件,需要的可以參考一下
    2022-05-05
  • Spring使用注解進(jìn)行對(duì)象裝配(DI)的操作

    Spring使用注解進(jìn)行對(duì)象裝配(DI)的操作

    獲取Bean對(duì)象也叫做對(duì)象裝配,就是把對(duì)象取出來放到某個(gè)類中,有時(shí)候也叫對(duì)象注入,這篇文章主要介紹了Spring使用注解進(jìn)行對(duì)象裝配(DI),需要的朋友可以參考下
    2023-07-07
  • java遞歸實(shí)現(xiàn)科赫雪花

    java遞歸實(shí)現(xiàn)科赫雪花

    這篇文章主要為大家詳細(xì)介紹了java遞歸實(shí)現(xiàn)科赫雪花,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • IDEA中sout快捷鍵無效問題的解決方法

    IDEA中sout快捷鍵無效問題的解決方法

    這篇文章主要介紹了IDEA中sout快捷鍵無效問題,在類文件中進(jìn)行操作會(huì)造成sout快捷命令無法自動(dòng)生成,比如操作了import引入其它包之后,本文給大家分享解決方法,感興趣的朋友一起看看吧
    2022-07-07
  • Mybatis中設(shè)置全局變量的方法示例

    Mybatis中設(shè)置全局變量的方法示例

    我們?cè)谄綍r(shí)的工作中有時(shí)候是需要在配置文件中配置全局變量的,我最近工作中就遇到了,所以索性記錄下來,下面這篇文章主要跟大家介紹了關(guān)于Mybatis中設(shè)置全局變量的方法示例,需要的朋友可以參考下。
    2017-07-07
  • java中的this引用及對(duì)象構(gòu)造初始化

    java中的this引用及對(duì)象構(gòu)造初始化

    這篇文章主要介紹了java中的this引用及對(duì)象構(gòu)造初始化,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • Spring Boot日志技術(shù)logback原理及配置解析

    Spring Boot日志技術(shù)logback原理及配置解析

    這篇文章主要介紹了Spring Boot日志技術(shù)logback原理及用法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07

最新評(píng)論

林芝县| 东乌| 盐边县| 梁山县| 高尔夫| 襄垣县| 茶陵县| 静海县| 繁峙县| 株洲县| 马公市| 平乡县| 中方县| 津南区| 花垣县| 清原| 上虞市| 卢湾区| 九龙县| 新源县| 宁阳县| 舟山市| 玛沁县| 伊金霍洛旗| 玉龙| 遵化市| 海盐县| 安新县| 正宁县| 互助| 西藏| 银川市| 德格县| 阿荣旗| 青海省| 定远县| 工布江达县| 东辽县| 滦南县| 泗水县| 大化|