一、resultMap简介
MyBatis是基于“数据库结构不可控”的思想建立的,也就是我们希望数据库遵循第三范式或BCNF,但实际事与愿违,那么结果集映射就是MyBatis为我们提供这种理想与现实间转换的手段了,而resultMap就是结果集映射的配置标签了。
1.从SQL查询结果到领域模型实体
在深入ResultMap标签前,我们需要了解从SQL查询结果集到JavaBean或POJO实体的过程。
①. 通过JDBC查询得到ResultSet对象
②. 遍历ResultSet对象并将每行数据暂存到HashMap实例中,以结果集的字段名或字段别名为键,以字段值为值
③. 根据ResultMap标签的type属性通过反射实例化领域模型
④. 根据ResultMap标签的type属性和id、result等标签信息将HashMap中的键值对,填充到领域模型实例中并返回
2.使用场景
在项目的实际开发中,有可能会遇到这样两种情况。
第一种 : 当你的数据库的列名跟你的属性名不配置的时候,
第二种:复杂查询(一对一的关系 ,一对多的关系)
id property=""> 只代表id 标签的实体类的属性名, column 代表的是你的数据库列名,其他的不是id的属性就用这个名称result
constructor - 类在实例化时,用来注入结果到构造方法中
result – 注入到字段或 JavaBean 属性的普通结果
association – 一个复杂的类型关联;许多结果将包成这种类型(一对一)
collection – 复杂类型的集(一对多)
discriminator – 使用结果值来决定使用哪个结果映射
case – 基于某些值的结果映射
id、result语句属性配置细节:
<id property="" column=""/>
<result property="" column=""/>
属性 | 描述 |
---|---|
property | 需要映射到JavaBean 的属性名称。 |
column | 数据表的列名或者标签别名。 |
javaType | 一个完整的类名,或者是一个类型别名。如果你匹配的是一个JavaBean,那MyBatis 通常会自行检测到。然后,如果你是要映射到一个HashMap,那你需要指定javaType 要达到的目的。 |
jdbcType | 数据表支持的类型列表。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果你是直接针对JDBC 编码,且有允许空的列,而你要指定这项。 |
typeHandler | 使用这个属性可以覆写类型处理器。这项值可以是一个完整的类名,也可以是一个类型别名。 |
代码(一对一):
<resultMap id="selectByRoleResult" type="User">
<id property="id" column="id"></id>
<result property="userName" column="userName"></result>
<result property="userRole" column="userRole"></result>
<!--在mybatis 配置 一对一的关系 ,拿到的是属性名, javaType 代表类型,可以给别名-->
<association property="role" javaType="Role">
<id property="id" column="r_id"></id>
<result property="roleName" column="roleName"></result>
<result property="roleCode" column="roleCode"></result>
</association>
</resultMap>
<select id="selectByRole" parameterType="User" resultMap="selectByRoleResult">
select u.*,r.id as r_id,r.roleName,r.roleCode from smbms_user u ,smbms_role r
where userName like concat ('%',#{userName},'%') and
userRole =#{userRole} and u.userRole = r.id
</select>
代码(一对多)
<resultMap id="selectAddressByNameResult" type="User">
<id property="id" column="a_id"></id>
<result property="userName" column="userName"></result>
<result property="userRole" column="userRole"></result>
<!--配置一对多,这里是ofType(必须有的)-->
<collection property="addressList" ofType="Address">
<id property="id" column="id"></id>
<result property="addressDesc" column="addressDesc"></result>
<result property="contact" column="contact"></result>
</collection>
</resultMap>
<select id="selectAddressByName" parameterType="String" resultMap="selectAddressByNameResult">
select u.* ,a.id as a_id,a.addressDesc ,a.contact from
smbms_user u inner join smbms_address a on u.id=a.userId and u.userName=#{userName}
</select>
使用注解的方式注入参数:
public List<User> selectUserByName(@Param("userName") String userName,@Param("userRole") Integer userRole);
二、动态SQL语句
MyBatis中用于实现动态SQL的元素主要有:
①if和where
where元素的作用是会在写入where元素的地方输出一个where,另外一个好处是你不需要考虑where元素里面的条件输出是什么样子的,MyBatis会智能的帮你处理。如果所有的条件都不满足那么MyBatis就会查出所有的记录;如果输出后是and这个单词开头的,MyBatis会把第一个单词and忽略,当然如果是or开头的,MyBatis也会把它忽略。此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上。
②choose (when, otherwise)
choose元素的作用就相当于JAVA中的switch语句,基本上跟JSTL中的choose的作用和用法是一样的,通常都是与when和otherwise搭配的。
③trim (where)
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能
④foreach
foreach的主要用在构建in条件中,它可以在SQL语句中迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束。
collection属性用于指定传入参数的类型。该属性是必须指定的,在不同情况下,该属性的值是不一样的,主要有以下3种情况:
如果传入的是单参数且参数类型是一个List类型的时候,collection属性值为list。
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array。
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map。实际上在传入参数的时候,MyBatis也是把它封装成一个Map的,List实例将会以“list”作为键,而数组实例将会以“array”作为键。这个时候collection属性值就是传入的List或array对象在封装自身的map里面中的对应key。
代码①:
<select id="selectUserByName" resultType="User">
select u.*,r.id from smbms_user u ,smbms_role r
<trim prefix="where" prefixOverrides="and" suffix="and u.userRole = r.id">
<if test="userRole!=null">
and userRole =#{ userRole}
</if>
<if test="userName != null and userName !=''">
and userName like concat ('%',#{userName},'%')
</if>
</trim>
</select>
代码②:
<update id="updateUser" parameterType="User">
update smbms_user
<trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
<if test="userCode != null ">userCode=#{userCode},</if>
<if test="userName != null">userName=#{userName},</if>
<if test="userPassword != null">userPassword=#{userPassword},</if>
<if test="gender != null">gender=#{gender},</if>
<if test="birthday != null">userName=#{birthday},</if>
</trim>
</update>
代码③
<select id="selecetArrayUser" resultType="User">
select * from smbms_user where userRole in
<foreach collection="array" item="uRole" open="(" separator="," close= ")">
#{uRole}
</foreach>
</select>
代码④:
<select id="selecetListUser" resultType="User">
select * from smbms_user where userRole in
<foreach collection="List" item="uRole" open="(" separator="," close=")">
#{uRole}
</foreach>
</select>