网上好多Mybatis的映射都有点老了,我自己查的时候发现多数都有问题或者描述不清,所以我参考Mybatis官网文档实现下多表联合查询。
2个表的左连接(A LEFT JOIN B 意思就是以A为主表连接B表,查出A表存在的行,如果该行B表不存在则B表查出数据为null)
Mybtis的XML配置如下:
customer_base_info(会员基本信息表)关联brand_integral_account(会员积分表)
这个映射方法是用Mybatis官网上的方法,这种的方法关联查询可以避免N+1查询问题。
<span style="font-family:Microsoft YaHei;font-size:14px;"><!-- 查询会员基本信息 --> <resultMap id="MemberInfoResultMap" type="cn.wonhigh.retail.crm.common.model.CustomerBaseInfo" > <id column="id" property="id" jdbcType="CHAR" /> <result column="no" property="no" jdbcType="VARCHAR" /> <result column="real_name" property="realName" jdbcType="VARCHAR" /> <result column="gender" property="gender" jdbcType="TINYINT" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="age" property="age" jdbcType="VARCHAR" /> <result column="birth_day" property="birthDay" jdbcType="DATE" /> <result column="identity_card" property="identityCard" jdbcType="VARCHAR" /> <result column="mob" property="mob" jdbcType="VARCHAR" /> <result column="referral_id" property="referralId" jdbcType="BIGINT" /> <!-- 关联brand_integral_account表 Column:The column name from the database, or the aliased column label that holds the value that will be passed to the nested statement as an input parameter. property:会从model获取数据 --> <association property="brandIntegralAccount" resultMap="BrandIntegralAccountResult"/> </resultMap> <resultMap id="BrandIntegralAccountResult" type="cn.wonhigh.retail.crm.common.model.BrandIntegralAccount" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="customer_id" property="customerId" jdbcType="BIGINT" /> <result column="brand_no" property="brandNo" jdbcType="VARCHAR" /> <result column="account_no" property="accountNo" jdbcType="VARCHAR" /> <result column="level_id" property="levelId" jdbcType="BIGINT" /> <result column="accumulated_score" property="accumulatedScore" jdbcType="BIGINT" /> <result column="remain_score" property="remainScore" jdbcType="BIGINT" /> <result column="status" property="status" jdbcType="TINYINT" /> <result column="join_date" property="joinDate" jdbcType="TIMESTAMP" /> <result column="join_shop_no" property="joinShopNo" jdbcType="VARCHAR" /> <result column="join_shop_name" property="joinShopName" jdbcType="VARCHAR" /> </resultMap> </span>
<span style="font-family:Microsoft YaHei;font-size:14px;"> <association property="brandIntegralAccount" resultMap="BrandIntegralAccountResult"/> </span>解释下这句话:
association这个是一对一映射的语法结构, 但是其实这两个表是一对多的关系, 正如我上一篇博客所说的Mybatis是面向结果的,很灵活,因为这个查询的结果被SQL(下面会提供)语句限制为一对一的结果, 所以映射的时候只要一对一映射就行了, 和表间关系无关。
property这个对应于你在Model层的属性,比如这个就是在CustomerBaseInfo.java这个Model里面写了
<span style="font-family:Microsoft YaHei;font-size:14px;">private BrandIntegralAccount brandIntegralAccount; public BrandIntegralAccount getBrandIntegralAccount () { return brandIntegralAccount; } public void set BrandIntegralAccount(BrandIntegralAccount brandIntegralAccount) { this.brandIntegralAccount = BrandIntegralAccount; }</span>这样在ResultSet映射的时候,关联的数据就注入到这个属性里面了。
resultMap=“BrandIntegralAccountResult”这个属性表示关联对象里面映射了哪写字段,“BrandIntegralAccountResult”就对应到了下面的那个resultMap id = “BrandIntegralAccountResult” 下的所有字段。
其他的属性:column对应你数据库表里面的字段名,property对应你Model里面定义的属性名,这样通过以上的配置,一对一的Mybatis就配置完了。
最后一步,也是最关键的一步,MySQL的编写:
<select id="selectMemberList" resultMap="MemberInfoResultMap"> SELECT customer_base_info.id, customer_base_info.real_name, customer_base_info.no, customer_base_info.mob, CASE gender WHEN 0 THEN '男' ELSE '女' END AS sex, customer_base_info.birth_day, brand_integral_account.status, brand_integral_account.brand_no, brand_integral_account.join_date, brand_integral_account.join_shop_name, (year(now())-year(customer_base_info.birth_day)-1) + ( DATE_FORMAT(customer_base_info.birth_day, '%m%d') <= DATE_FORMAT(NOW(), '%m%d') ) as age FROM customer_base_info LEFT JOIN brand_integral_account ON brand_integral_account.customer_id=customer_base_info.id WHERE 1=1 <include refid="memberlistcondition" /> <if test="orderByField != null and ''!=orderByField" > order by ${orderByField} <if test="orderByField" > ${orderBy} </if> </if> LIMIT #{page.startRowNum} ,#{page.pageSize} </select>id是你在DAO层或者说DAL层调用时用到的方法名,resultMap就是在上面配置的关联映射。
这句话就将生日转换成年龄用的:
(year(now())-year(customer_base_info.birth_day)-1) + ( DATE_FORMAT(customer_base_info.birth_day, '%m%d') <= DATE_FORMAT(NOW(), '%m%d') ) as age
注意上面这句话的<(小于号)在xml里面得做个转换如下表:
< |
< |
小于号 |
> |
> |
大于号 |
& |
& |
和 |
' |
’ |
单引号 |
" |
" |
双引号 |
根据两个表的customer_id和id关联的结果如下: