【SSM - MyBatis篇05】映射器 - resultMap结果映射 - 级联关系 - 一对一、一对多、多对多关联查询

映射器

  MyBatis 的真正强大在于它的语句映射。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
MyBatis文档地址:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

XML映射器

元素名称 描 述 备 注
select 映射查询语句,最常用、最复杂的元素之一 可以自定义参数,返回结果集等
insert 映射插入语句 执行后返回一个整数,代表插入的行数
update 映射更新语句 执行后返回一个整数,代表更新的行数
delete 映射删除语句 执行后返回一个整数,代表删除的行数
sql 定义一部分SQL,在多个位置被引用–被其它语句引用的可重用的语句块 例如,一张表列名,一次定义,可1以在多个SQL语句中使用
resultMap 用来描述从数据库结果集中来加载对象,是最复杂也是最强大的元素 提供映射规则
cache-ref 引用其它命名空间的缓存配置 提供其它命名空间下的缓存映射
cache 该命名空间的缓存配置 分为一级缓存和二级缓存

1. select元素【**】

  MyBatis的查询语句

属性名称 描 述
id 它和Mapper的命名空间组合起来使用,是唯一标识符,供MyBatis调用
parameterType 表示传入SQL语句的参数类型的全限定名或别名。是个可选属性,MyBatis能推断出具体传入语句的参数。
resultType SQL语句执行后返回的类型(全限定名或者别名)。如果是集合类型,返回的是集合元素的类型。返回时可以使用resultType或resultMap之一
resultMap 它是映射集的引用,与< resultMap>元素一起使用。返回时可以使用resultType或resultMap之一
flushCache 它的作用是在调用SQL语句后,是否要求MyBatis清空之前查询本地缓存和二级缓存。默认值为false。如果设置为true,则任何时候只要SQL语句被调用,都将清空本地缓存和二级缓存
useCache 启动二级缓存的开关。默认值为true,表示将查询结果存入二级缓存中
timeout 用于设置超时参数,单位是秒。超时将抛出异常。
fetchSize 获取记录的总条数设定
statementType 告诉MyBatis使用哪个JDBC的Statement工作,取值为STATEMENT(Statement)、PREPARED(PreparedStatement)、CALLABLE(CallableStatement)
resultSetType 这是针对JDBC的ResultSet接口而言,其值可设置为FORWARD_ONLY(只允许向前访问)、SCROLL_SENSITIVE(双向滚动,但不及时更新)、SCROLL_INSENSITIVE(双向滚动,及时更新)

2. insert元素

  insert元素用于映射插入语句,update元素用于映射更新语句,delete元素用于映射删除语句。执行insert都将返回一个整数表示其影响的行数。

2.1 insert元素特有的属性:

insert的特有属性 描述
keyProperty 该属性的作用是将插入或更新操作时的返回值赋值给PO类的某个属性,通常会设置为主键对应的属性。如果是联合主键,可以在多个值之间用逗号隔开。
keyColumn 该属性用于设置第几列是主键,当主键列不是表中的第一列时需要设置。如果是联合主键时,可以在多个值之间用逗号隔开。
useGeneratedKeys 该属性将使MyBatis使用JDBC的getGeneratedKeys()方法获取由数据库内部生产的主键,如MySQL、SQL Server等自动递增的字段,其默认值为false

2.2 insert元素主键回填(设置为自动递增的主键)

MySQL、SQL Server等数据库的表格可以采用自动递增的字段作为主键。有时可能需要使用这个刚刚产生的主键,用以关联其他业务。

<!-- 添加一个用户,成功后将主键值回填给uid(javabean类的属性)-->
	<insert id="addUser" parameterType="com.po.MyUser" 
	keyProperty="uid" useGeneratedKeys="true">
		insert into user (uname,usex) values(#{uname},#{usex})
	</insert>

2.3 自定义主键(实现主键自动递增)

如果实际工程中使用的数据库不支持主键自动递增(如Oracle),或者取消了主键自动递增的规则时,可以使用MyBatis的**< selectKey >元素来自定义生成主键。**

	<insert id="insertUser" parameterType="com.xgf.bean.User">
		<!-- 先使用selectKey元素定义主键,然后再定义SQL语句 -->
		<selectKey keyProperty="uid" resultType="Integer" order="BEFORE">
		   select if(max(uid) is null, 1 , max(uid)+1) as newUid from user
		</selectKey>
		insert into user (uid,uname,usex) values(#{uid},#{uname},#{usex})
    </insert>


3. update、delete元素

和元素比较简单,它们的属性和元素、元素的属性差不多,执行后也返回一个整数,表示影响了数据库的记录行数

	 <!-- 修改一个用户 -->
    <update id="updateUser" parameterType="com.xgf.bean.User">
		update user set uname = #{uname},usex = #{usex} where uid = #{uid}
    </update>
    <!-- 删除一个用户 -->
    <delete id="deleteUser" parameterType="Integer"> 
		delete from user where uid = #{uid}
    </delete>


4. resultMap元素(结果映射)【*****】

  resultMap元素表示结果映射集,是MyBatis中最重要也是最强大的元素。主要用来定义映射规则、级联的更新以及定义类型转化器等。

resultMap标签的属性:

resultMap属性 描述
id 当前命名空间中的一个唯一标识,用于标识一个结果映射。
type 类的完全限定名, 或者一个类型别名。
autoMapping 如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。默认值:未设置(unset)。

resultMap的子元素:

<resultMap type="" id="">
    <constructor>		<!-- 类在实例化时,用来注入结果到构造方法 -->
		<idArg/>		<!-- ID参数,结果为ID -->
		<arg/>			<!-- 注入到构造方法的一个普通结果 -->
    </constructor>
    <id/>				<!-- 用于表示哪个列是主键 -->
    <result/>			<!-- 注入到字段或JavaBean属性的普通结果,非主键外的 -->
    <association property=""/>		<!-- 用于一对一关联 -->
    <collection property=""/>		<!-- 用于一对多、多对多关联 -->
    <discriminator javaType="">		<!-- 使用结果值来决定使用哪个结果映射 -->
        <case value=""/>			<!-- 基于某些值的结果映射 -->
    </discriminator>
</resultMap>

基本案例写法:

	<!-- 自定义resultMap 结果集类型 -->
	<resultMap type="com.xgf.bean.User" id="userResultMap">
		<!-- property对应的是javabean类中的属性-->
		<!-- column对应的是数据库表的列名,可以来自不同的表 -->
		<id property="uid" column="uid"/>
		<result property="uname" column="uname"/>
		<result property="usex" column="usex"/>
	</resultMap>
	
	<!-- 使用自定义结果集类型查询所有用户 -->
	<select id="selectAllUser" resultMap="userResultMap">
		select uid,uname,usex from user
	</select>

级联关系【*****】

4.1 一对一关联查询 (association) - 用javaType来指定对象类型

  MyBatis中,通过<resultMap>元素的子元素<association>处理这种一对一级联关系。

属性 描述
property 指定映射到实体类的对象属性(javabean对应的对象属性值) ---- 就是一对一关联的对象(定义的bean中的对象属性名)
javaType 指定映射到实体对象属性的类型(javabean对象的完全限定名/类型别名) —就是一对一关联的对象的完全限定名,或别名
select 指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询。
	<!-- 一对一关联查询 person人和card身份证-->
	<resultMap id="personMap" type="com.xgf.correlation.one_to_one.bean.Person" autoMapping="true">
        <!--
            <id>主键
            <result>其它属性列 
            如果设置了autoMapping="true" 自动映射,那么数据库表列名和类对象属性名一致的情况下
            ,可以不用写<result>属性,自动映射
        -->
       <id property="id" column="id"/>
       <result property="username" column="username"/>
        <!--
           封装person对象对应的card
           一对一关联 用association封装对象类型
           property就是关联对象card在的person类中的属性值,javaType就是person关联的对象完全限定名
        -->
       <association property="card" javaType="com.xgf.correlation.one_to_one.bean.Card">
           <id property="id" column="id"/>
           <result property="code" column="code"/>
       </association>

    </resultMap>

<!--  查询结构封装成map对象  -->
    <select id="getPersonById" resultMap="personMap">
        select p.id,p.username,c.id,c.code
        from person p inner join card c on p.id_card = c.id
        where p.id = #{id}
    </select>
4.2 一对多、多对多关联查询 (collection) - 用ofType来制定对象类型

  多对多关联就是两个一对多关联进行交互替换。

一对多关联查询:

<!--一对多关联关系 user和task表  一个user可以有多个task任务,一个task只能由一个user完成-->
   <resultMap id="userTaskMap" type="com.xgf.correlation.one_to_many.bean.User">
        <id column="id" property="id"/>
        <result property="username" column="username"/>

		<!-- property就是在user中定义的task集合的属性名taskList
			ofType就是对应这个集合的属性类task类的完全限定名	
		 -->
        <collection property="taskList" ofType="com.xgf.correlation.one_to_many.bean.Task" >
            <id column="tid" property="id"/>
            <result column="taskName" property="taskName"/>
        </collection>
    </resultMap>

    <select id="getUserTaskById" resultMap="userTaskMap">
        SELECT u.id,u.username,t.id tid,t.taskName
        from users u inner join task t on u.id = t.userId
        where u.id=#{id}
    </select>

多对多关联查询:

	<!-- order订单表和product 产品表,一个订单可以有多份产品,一个产品可以有多个订单
		创建中间表orders_product
	 -->
 	<resultMap id="orderMap" type="com.xgf.mybatis.correlation.many_to_many.bean.Order">
        <id column="oid" property="id"/>
        <result property="description" column="description"/>
        <collection property="productList" ofType="com.xgf.mybatis.correlation.many_to_many.bean.Product">
            <id column="pid" property="id"/>
            <result property="name" column="name"/>
        </collection>
    </resultMap>

    <select id="getOrderById" parameterType="int" resultMap="orderMap">
           select o.id oid,o.description,p.id pid,p.name
            from orders o left outer join orders_product op on o.id = op.ordersId
                          left outer join product p on p.id = op.productId
            where o.id = #{id}

    </select>

猜你喜欢

转载自blog.csdn.net/qq_40542534/article/details/108814695