mybatis 之association用法

这几天要用mybatis的association关联映射,好久没用忘了好多,记下来备用。
最基本的用法网上到处都是,就不写了,简单说说用的时候遇到的坑。

//要映射的类
public class TourGroupForCarCar implements Serializable {
    private static final long serialVersionUID = 2412973487524417016L;
    private TourGroup tourGroup;
    private String operatorMobile;
    private Integer guideId;
    private String guideName;
    private String guideMobile;

    public String getOperatorMobile() {
        return operatorMobile;
    }

    public void setOperatorMobile(String operatorMobile) {
        this.operatorMobile = operatorMobile;
    }

    public String getGuideMobile() {
        return guideMobile;
    }

    public void setGuideMobile(String guideMobile) {
        this.guideMobile = guideMobile;
    }

    public Integer getGuideId() {
        return guideId;
    }

    public void setGuideId(Integer guideId) {
        this.guideId = guideId;
    }

    public String getGuideName() {
        return guideName;
    }

    public void setGuideName(String guideName) {
        this.guideName = guideName;
    }

    public TourGroup getTourGroup() {
        return tourGroup;
    }

    public void setTourGroup(TourGroup tourGroup) {
        this.tourGroup = tourGroup;
    }
}
//mapper文件
<resultMap id="tourGroupForCarCar" type="com.yimayhd.erpcenter.dal.sales.client.sales.po.TourGroupForCarCar">

    <result property="guideId" column="guide_id" />
    <result property="guideName" column="guide_name" />
    <result property="guideMobile" column="guide_mobile" />
    <association property="tourGroup" resultMap="BaseResultMap" />
        <!--<id column="id" property="id" jdbcType="INTEGER" />
        <result column="operator_name" property="operatorName" jdbcType="VARCHAR" />
        <result column="operator_id" property="operatorId" jdbcType="INTEGER" />
        <result column="total_adult" property="totalAdult" jdbcType="INTEGER" />
        <result column="total_child" property="totalChild" jdbcType="INTEGER" />
        <result column="total_guide" property="totalGuide" jdbcType="INTEGER" />
        <result column="group_mode" property="groupMode" jdbcType="INTEGER" />
        <result column="group_code" property="groupCode" jdbcType="VARCHAR" />
        <result column="date_start" property="dateStart" jdbcType="DATE" />
        <result column="date_end" property="dateEnd" jdbcType="DATE" />
        <result column="remark" property="remark" jdbcType="VARCHAR" />
        <result column="prudct_brand_id" property="prudctBrandId"
                jdbcType="INTEGER" />
        <result column="product_brand_name" property="productBrandName"
                jdbcType="VARCHAR" />
        <result column="product_id" property="productId" jdbcType="INTEGER" />
        <result column="product_name" property="productName" jdbcType="VARCHAR" />
        <result column="daynum" property="daynum" jdbcType="INTEGER" />
        <result column="order_num" property="orderNum" jdbcType="INTEGER" />
    </association>-->
</resultMap>
//BaseResultMap是自己定义的另一个resultMap。如果写成注释的样子,association里就得用javaType属性了。
//sql语句
<select id="selectGroupInfoWithArrangedTransForCarCar" resultMap="tourGroupForCarCar" parameterType="com.yihg.mybatis.utility.PageBean" >
        select tg.id,group_mode, prudct_brand_id,
        product_brand_name,
        product_id,
        product_name, date_start, date_end,daynum,
        ifnull(total_adult,0) total_adult,
        ifnull(total_child,0) total_child,
        ifnull(total_guide,0) total_guide, tg.remark,
         tg.operator_id, tg.operator_name,order_num,bg.`guide_id`,bg.`guide_name`,bg.`guide_mobile`
        from tour_group tg join booking_delivery bd on tg.id=bd.group_id
        JOIN booking_guide bg ON  tg.`id`= bg.`group_id`
         where tg.create_time <![CDATA[>=]]> #{page.parameter.startTime}
          and tg.create_time <![CDATA[<=]]> #{page.parameter.endTime}
        and bd.supplier_name like concat ('%','${page.parameter.supplierName}','%')
        AND bg.`is_default` = 1
    </select>
//('%','${page.parameter.supplierName}','%')中间的参数不加引号的话会报错:未知的列。
public class GroupOrderForCarCar implements Serializable {
    private static final long serialVersionUID = -707282179483459490L;

    private List<GroupOrder> groupOrderList;
    private String groupCode;
    private String guestReresentativeName;

    public List<GroupOrder> getGroupOrderList() {
        return groupOrderList;
    }

    public void setGroupOrderList(List<GroupOrder> groupOrderList) {
        this.groupOrderList = groupOrderList;
    }

    public String getGroupCode() {
        return groupCode;
    }

    public void setGroupCode(String groupCode) {
        this.groupCode = groupCode;
    }

    public String getGuestReresentativeName() {
        return guestReresentativeName;
    }

    public void setGuestReresentativeName(String guestReresentativeName) {
        this.guestReresentativeName = guestReresentativeName;
    }
}
//mapper文件<resultMap id="groupOrderForCarCar" type="com.yimayhd.erpcenter.dal.sales.client.sales.po.GroupOrderForCarCar">

        <result property="groupCode" column="group_code"/>
        <collection  ofType="com.yimayhd.erpcenter.dal.sales.client.sales.po.GroupOrder" property="groupOrderList">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="product_name" property="productName" jdbcType="VARCHAR" />
            <result column="product_brand_name" property="productBrandName" jdbcType="VARCHAR" />
            <result column="num_adult" property="numAdult" jdbcType="INTEGER" />
            <result column="num_child" property="numChild" jdbcType="INTEGER" />
            <result column="num_guide" property="numGuide" jdbcType="INTEGER" />
            <result column="supplier_name" property="supplierName" jdbcType="VARCHAR" />
            <result column="supplier_id" property="supplierId" jdbcType="INTEGER" />
            <result column="receive_mode" property="receiveMode" jdbcType="VARCHAR" />
            <result column="group_id" property="groupId" jdbcType="INTEGER" />
            <result column="order_type" property="orderType" jdbcType="INTEGER" />
            <result column="departure_date" property="departureDate" jdbcType="VARCHAR" />
            <result column="product_id" property="productId" jdbcType="INTEGER" />
            <result column="product_brand_id" property="productBrandId" jdbcType="INTEGER" />
            <result column="type" property="type" jdbcType="INTEGER" />
            <result column="remark" property="remark" jdbcType="VARCHAR" />
            <result column="total" property="total" jdbcType="DECIMAL" />
            <result column="contact_name" property="contactName" jdbcType="VARCHAR" />
            <result column="contact_tel" property="contactTel" jdbcType="VARCHAR" />
            <result column="contact_mobile" property="contactMobile" jdbcType="VARCHAR" />
            <result column="contact_fax" property="contactFax" jdbcType="VARCHAR" />
            <result column="order_no" property="orderNo" jdbcType="VARCHAR" />
        </collection>
    </resultMap>
<select id="selectGroupOrdersInOneGroupForCarCar" resultMap="groupOrderForCarCar" parameterType="com.yihg.mybatis.utility.PageBean">
        select go.id, group_id, supplier_id,supplier_name,
        order_no,order_type,`type`,
        total,
        contact_name,
        contact_tel,
        contact_mobile, contact_fax,
        num_adult,
        num_child,
        num_guide,
        departure_date, go.product_id,
        go.product_brand_id,
        go.product_brand_name,
        go.product_name,
        receive_mode,
        go.remark,tg.group_code
        from group_order go left join tour_group tg on go.group_id = tg.id
        where   group_id IN <foreach item="item" index="index" collection="page.parameter.groupIdSet" open="("
                 separator="," close=")">
            #{item}
        </foreach>
    </select>
//上面的实体类中的groupOrder刚开始用的单个对象GroupOrder,我用sql查出来的记录是12条,但是mybatis却一直返回2条,想了好一会儿,才意识到mybatis的映射结果和sql语句直接查询的结果是不一样的:mybatis中,两表关联后,使用in语法查出来的记录数,应该是小于等于groupIdSet集合的大小的。tour_group和group_order是一对多的关系,而上面的实体类和tour_group中的group_code(在tour_group表中唯一)是一对一的关系,因此映射时上面的实体类和group_order也应该是一对多的关系,返回的group_order映射到了对应的groupOrderList集合中。所以实际确实是返回两条记录,每条记录中包含一个group_order的集合,所有这样的集合总大小是12。而不会如sql查询那样直接返回12条记录。
<think>嗯,用户想了解MyBatisassociation标签的使用方法和示例。首先,我需要回顾一下association标签的基本概念。根据引用[2],association用于处理“有一个”类型的关系,比如一个博客有一个用户。这通常对应数据库中的一对一关系。 接下来,我应该整理association的两种主要实现方式:嵌套查询和嵌套结果映射。用户可能需要具体的配置示例,所以得结合引用中的例子来说明。比如引用[1]中的userWithDetailResultMap,展示了如何通过association将用户和详细信息关联起来。 还要注意提到javaType属性的使用,虽然MyBatis有时能自动推断,但显式声明更安全。另外,如果存在多个关联表的情况,需要指定columnPrefix,如引用[3]中处理部门员工时的情况。 用户可能遇到的问题包括性能优化,比如N+1查询问题,这时候需要介绍懒加载配置。同时,区分association和collection的不同应用场景也很重要,避免用户混淆。 最后,要确保回答结构清晰,分步骤讲解,并给出实际代码示例和配置片段,帮助用户逐步理解和应用association标签。同时,生成的相关问题要覆盖常见的使用场景和潜在问题,方便用户进一步学习。</think>### MyBatis association 标签使用详解 #### 一、基本概念与使用场景 `<association>`标签用于处理**对象间的一对一关联关系**,例如用户与用户详细信息的关系(每个用户对应唯一详细信息)。通过该标签可实现查询结果中嵌套对象的自动映射[^2]。 #### 二、核心实现方式 ##### 1. 嵌套查询(N+1查询) ```xml <resultMap id="userResultMap" type="User"> <id property="id" column="id"/> <result property="name" column="name"/> <association property="detail" column="id" select="selectUserDetail"/> </resultMap> <select id="selectUserDetail" resultType="UserDetail"> SELECT * FROM user_detail WHERE user_id = #{id} </select> ``` * 特点:通过`select`属性指定子查询 * 注意:需启用懒加载避免N+1问题 ##### 2. 嵌套结果映射(联表查询) ```xml <resultMap id="userWithDetailResultMap" type="com.example.User"> <id property="userId" column="user_id"/> <result property="username" column="username"/> <association property="detail" javaType="com.example.UserDetail"> <id property="detailId" column="detail_id"/> <result property="age" column="age"/> <result property="address" column="address"/> </association> </resultMap> ``` * 特点:通过单条SQL的联表查询获取所有数据 * 优势:比嵌套查询性能更优[^1] #### 三、高级配置参数 | 参数名 | 作用说明 | 示例值 | |----------------|---------------------------------|---------------------------| | property | 主对象中的属性名 | detail | | javaType | 关联对象的Java类型 | com.example.UserDetail | | column | 用于关联查询的列名 | user_id | | columnPrefix | 列名前缀(处理联表查询字段冲突) | detail_ | #### 四、完整示例(含SQL) ```xml <select id="selectUserWithDetail" resultMap="userWithDetailResultMap"> SELECT u.user_id, u.username, d.detail_id, d.age, d.address FROM users u LEFT JOIN user_detail d ON u.user_id = d.user_id WHERE u.user_id = #{id} </select> ``` #### 五、最佳实践建议 1. **性能优化**:优先使用嵌套结果映射方式 2. **命名规范**:使用`columnPrefix`避免字段冲突 3. **类型处理**:显式指定`javaType`保证映射正确性 4. **懒加载配置**:需在全局配置中启用`lazyLoadingEnabled` #### 六、与collection的差异对比 || association | collection | |---|---|---| | 关系类型 | 一对一 | 一对多 | | Java类型 | 单个对象 | 集合类型 | | 典型场景 | 用户↔详细信息 | 部门↔员工列表[^3] |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天进步一点_点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值