前言:最近有空重新回顾了一下Mybatis
的用法,结合自己项目中的实际应用,发现自己并没有有效的使用Mybatis
的各种功能,特别是在结果映射的使用上面,于是结合这次项目重新优化了一下项目。
一、相关概念
Mybatis
结果映射主要是resultMap
的配置,resultMap
主要有以下几个节点属性
<resultMap>
<constructor>
<idArg/>
<arg/>
</constructor>
<id/>
<result/>
<association property=""/>
<collection property""/>
<discriminator javaType="">
<case value=""></case>
</discriminator>
</resultMap>
其中id
和result
是我们常用的两个节点属性,其他几个在目前的项目中,几乎没有用到,于是一个一个来。
二、constructor
constructor
主要是用来配置构造方法,默认的情况之下,mybatis
会调用实体类的无参构造方法,创建一个实例,然后再给相关的属性赋值,如果我们手动给实体类设置了有参的构造方法,又没有创建无参的构造方法,那么如果不进行特殊的配置,resultMap
在生成实体类的时候就会进行报错,因为他没有找到无参的构造方法。
具体例子,配置如下
<resultMap id="userResultMap" type="org.sang.bean.User">
<constructor>
<idArg column="id" javaType="long"/>
<arg column="username" javaType="string"/>
<arg column="password" javaType="string"/>
<arg column="address" javaType="string"/>
</constructor>
</resultMap>
其中 idArg
标记出作为ID
的结果,可以帮助提高整体的性能。
三、association
association
可以映射出复杂的实体类,如果返回的实体类中有另外一个实体类的属性,那么可以使用association
进行配置。下面举个例子:
例如,我们在查询用户信息的时候需要把用户的角色也查出来,这时候我现在的做法是先查出来用户的数据,然后再根据用户的role_id
或者其他条件查出相关Role
,然后再把角色的值赋值到User
的role
属性中。
如果利用association
就可以一步到位。
<resultMap id="userMap" type="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<result property="address" column="address"></result>
<result property="email" column="email"></result>
<association property="role" javaType="Role">
<id property="id" column="role_id"></id>
<result property="name" column="role_name"></result>
</association>
</resultMap>
注意
其实这里有一个更快捷的方法,主要是利用 Mybatis
解析返回值的相关底层原理,可以自动创建role
对象,并且把值写进到属性中。
select u.id, u.username, u.password,u.address,u.email, r.id as role.id, r.name as role.name
from user u left join user_roles ur on ur.user_id = u.id
left join role r on r.id = ur.role_id
三、collection
collection
的使用场景实际上在项目中非常的常见,比如后台管理系统中,用户的角色往往会对应挂接的菜单列表,一个订单往往会对应着商品明细列表,这时候查询结果都是一对多的关系,之前我在项目中的写法都是分开查询,然后在把结果组装起来,这样性能比较差,且代码不够整洁。
以订单中使用作为例子。
需求:查询某个订单的详情,包括订单明细。
分析:数据库中订单有两个表,主表保存,订单的主要信息,子表保存订单的详细商品信息。
处理:XML
中的具体代码如下
<sql id="Base_Column_List">
toi.id, toi.number, toi.date, toi.custom_id, toi.custom_name,
toi.create_time, toi.last_update_time, toi.order_number, toi.phone, toi.address,
toie.id, toie.parent_id, toie.parent_number, toie.goods_id, toie.goods_number, toie.goods_name,
toie.standard, toie.unit_id, toie.unit_name, toie.unit_count, toie.aux_unit_id, toie.aux_unit_name,
toie.aux_unit_count, toie.price, total_price, toie.remark, toie.create_time
</sql>
<resultMap id="orderMessageResultMap" type="org.guoxn.order.api.model.OrderInfo">
<id property="id" column="id"/>
<result property="number" column="number"/>
<result column="date" property="date" jdbcType="VARCHAR" />
<result column="custom_id" property="customId" jdbcType="VARCHAR" />
<result column="custom_name" property="customName" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="VARCHAR" />
<result column="last_update_time" property="lastUpdateTime" jdbcType="VARCHAR" />
<result column="phone" property="phone" jdbcType="VARCHAR" />
<result column="address" property="address" jdbcType="VARCHAR" />
<result column="order_number" property="orderNumber" jdbcType="VARCHAR" />
<collection property="orderEntryList" ofType="org.guoxn.order.api.model.OrderInfoEntry">
<id property="id" column="parent_id"/>
<result column="parent_number" property="parentNumber" jdbcType="VARCHAR"/>
<result column="goods_id" property="goodsId" jdbcType="CHAR"/>
<result column="goods_name" property="goodsName" jdbcType="VARCHAR"/>
<result column="goods_number" property="goodsNumber" jdbcType="VARCHAR"/>
<result column="standard" property="standard" jdbcType="VARCHAR"/>
<result column="unit_id" property="unitId" jdbcType="CHAR"/>
<result column="unit_name" property="unitName" jdbcType="VARCHAR"/>
<result column="unit_count" property="unitCount" jdbcType="DOUBLE"/>
<result column="aux_unit_id" property="auxUnitId" jdbcType="CHAR"/>
<result column="aux_unit_name" property="auxUnitName" jdbcType="VARCHAR"/>
<result column="aux_unit_count" property="auxUnitCount" jdbcType="DOUBLE"/>
<result column="price" property="price" jdbcType="DOUBLE"/>
<result column="total_price" property="totalPrice" jdbcType="DOUBLE"/>
<result column="remark" property="remark" jdbcType="VARCHAR"/>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
</collection>
</resultMap>
<select id="selectOrderInfo" resultMap="orderMessageResultMap">
select <include refid="Base_Column_List"/>
from t_order_info toi left join t_order_info_entry toie
on toi.id = toie.parent_id
where toi.id = #{id}
</select>
调用该方法就可以得到一个订单实例,并且包含其订单的详细品项的数组属性。
总结:
Mybatis
有很多易用且方便的能够快速提升开发效率的用法,作为一个新项目几乎必用的组件,一定要善于使用它。