MyBatis中resultType和parameterType和resultMap使用总结

发布时间:

这篇文章主要介绍了MyBatis中resultType和parameterType和resultMap使用总结,具有很好的参考价值,希望对大家有所帮助。

MyBatis中resultType和parameterType和resultMap使用总结

resultType 与 parameterType 的基本使用的区别

1、使用 resultType:主要针对于从数据库中提取相应的数据出来

2、使用parameterType:主要针对于 将信息存入到数据库中 如: insert 增加数据到数据库zhong Update等

  • resultType是sql语句查询结果集的封装类型,也就是说把sql查询的结果封装在bean里返回回去,是存数据用的。
  • paramType是从传过来的Bean中取数据放进例如insert语句的values中当实参用,是取数据用的。

MyBatis中 resultType 和 resultMap 的区别

resultType和resultMap功能类似 ,都是返回对象信息 ,但是resultMap要更强大一些 ,可自定义。

因为resultMap要配置一下,表和类的一一对应关系,所以说就算你的字段名和你的实体类的属性名不一样也没关系,都会给你映 射出来,但是,resultType就比较鸡肋了,必须字段名一样,比如说 cId和c_id 这种的都不能映射 。

下面介绍几个常用的映射关系:

1.单表查询

resultMap:当使用resultMap做SQL语句返回结果类型处理时,通常需要在mapper.xml中定义resultMap进行pojo和相应表字段的对应。

<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
    <!-- 配置映射的订单信息 -->
    <!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
        column:订单信息的唯 一标识 列
        property:订单信息的唯 一标识 列所映射到Orders中哪个属性
      -->
    <id column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime"/>
    <result column="note" property="note"/>        
</resultMap>

2.关联查询(一对一)

resultMap对于一对一表连接的处理方式通常为在主表的pojo中添加嵌套另一个表的pojo,然后在mapper.xml中采用association节点元素进行对另一个表的连接处理。例如

<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
    <!-- 配置映射的订单信息 -->
    <!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
        column:订单信息的唯 一标识 列
        property:订单信息的唯 一标识 列所映射到Orders中哪个属性
      -->
    <id column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime"/>
    <result column="note" property=note/>
    
    <!-- 配置映射的关联的用户信息 -->
    <!-- association:用于映射关联查询单个对象的信息
    property:要将关联查询的用户信息映射到Orders中哪个属性
     -->
    <association property="user"  javaType="cn.itcast.mybatis.po.User">
        <!-- id:关联查询用户的唯 一标识
        column:指定唯 一标识用户信息的列
        javaType:映射到user的哪个属性
         -->
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
    
    </association>
</resultMap>

3.关联查询(一对多)

resultMap的处理方式为在订单表数据的pojo中添加一个list,list中为订单明细表的属性,在mapper.xml中采用如下的处理方式:

订单及订单明细的resultMap 使用extends继承,不用在中配置订单信息和用户信息的映射

<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">
     <!- 订单信息 -->
    <!- 用户信息 -->
    <!- 使用extends继承,不用在中配置订单信息和用户信息的映射 -->
    <!- 订单明细信息
    一个订单关联查询出了多条明细,要使用collection进行映射
    collection:对关联查询到多条记录映射到集合对象中
    property:将关联查询到多条记录映射到cn.itcast.mybatis.po.Orders哪个属性
    ofType:指定映射到list集合属性中pojo的类型
     -->
     <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
         <!-- id:订单明细唯 一标识
         property:要将订单明细的唯 一标识 映射到cn.itcast.mybatis.po.Orderdetail的哪个属性
           -->
         <id column="orderdetail_id" property="id"/>
         <result column="items_id" property="itemsId"/>
         <result column="items_num" property="itemsNum"/>
         <result column="orders_id" property="ordersId"/>
     </collection>
    

</resultMap>

样例 student表(增删改查)

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.dao.StudentMapper">
  <resultMap id="BaseResultMap" type="com.qcby.entity.Student">
    <id column="Sid" jdbcType="INTEGER" property="sid" />
    <result column="Snum" jdbcType="VARCHAR" property="snum" />
    <result column="Spassword" jdbcType="VARCHAR" property="spassword" />
    <result column="Sname" jdbcType="VARCHAR" property="sname" />
    <result column="Ssex" jdbcType="VARCHAR" property="ssex" />
    <result column="Sgrade" jdbcType="VARCHAR" property="sgrade" />
    <result column="Smajor" jdbcType="VARCHAR" property="smajor" />
  </resultMap>
  <sql id="Base_Column_List">
    Sid, Snum, Spassword, Sname, Ssex, Sgrade, Smajor
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from student
    where Sid = #{sid,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from student
    where Sid = #{sid,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.qcby.entity.Student">
    insert into student (Sid, Snum, Spassword,
      Sname, Ssex, Sgrade, 
      Smajor)
    values (#{sid,jdbcType=INTEGER}, #{snum,jdbcType=VARCHAR}, #{spassword,jdbcType=VARCHAR}, 
      #{sname,jdbcType=VARCHAR}, #{ssex,jdbcType=VARCHAR}, #{sgrade,jdbcType=VARCHAR}, 
      #{smajor,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="com.qcby.entity.Student">
    insert into student
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="sid != null">
        Sid,
      </if>
      <if test="snum != null">
        Snum,
      </if>
      <if test="spassword != null">
        Spassword,
      </if>
      <if test="sname != null">
        Sname,
      </if>
      <if test="ssex != null">
        Ssex,
      </if>
      <if test="sgrade != null">
        Sgrade,
      </if>
      <if test="smajor != null">
        Smajor,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="sid != null">
        #{sid,jdbcType=INTEGER},
      </if>
      <if test="snum != null">
        #{snum,jdbcType=VARCHAR},
      </if>
      <if test="spassword != null">
        #{spassword,jdbcType=VARCHAR},
      </if>
      <if test="sname != null">
        #{sname,jdbcType=VARCHAR},
      </if>
      <if test="ssex != null">
        #{ssex,jdbcType=VARCHAR},
      </if>
      <if test="sgrade != null">
        #{sgrade,jdbcType=VARCHAR},
      </if>
      <if test="smajor != null">
        #{smajor,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.qcby.entity.Student">
    update student
    <set>
      <if test="snum != null">
        Snum = #{snum,jdbcType=VARCHAR},
      </if>
      <if test="spassword != null">
        Spassword = #{spassword,jdbcType=VARCHAR},
      </if>
      <if test="sname != null">
        Sname = #{sname,jdbcType=VARCHAR},
      </if>
      <if test="ssex != null">
        Ssex = #{ssex,jdbcType=VARCHAR},
      </if>
      <if test="sgrade != null">
        Sgrade = #{sgrade,jdbcType=VARCHAR},
      </if>
      <if test="smajor != null">
        Smajor = #{smajor,jdbcType=VARCHAR},
      </if>
    </set>
    where Sid = #{sid,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.qcby.entity.Student">
    update student
    set Snum = #{snum,jdbcType=VARCHAR},
      Spassword = #{spassword,jdbcType=VARCHAR},
      Sname = #{sname,jdbcType=VARCHAR},
      Ssex = #{ssex,jdbcType=VARCHAR},
      Sgrade = #{sgrade,jdbcType=VARCHAR},
      Smajor = #{smajor,jdbcType=VARCHAR}
    where Sid = #{sid,jdbcType=INTEGER}
  </update>
  <select id="stushow"  resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from student
  </select>
  <select id="selectStuBySnum" parameterType="java.lang.String" resultType="com.qcby.entity.Student">
    select
    <include refid="Base_Column_List" />
    from student
    where Snum = #{Snum,jdbcType=VARCHAR}
  </select>
  <select id="selectStuLogin" parameterType="com.qcby.entity.Student" resultType="com.qcby.entity.Student">
    select
    <include refid="Base_Column_List" />
    from student
    where Snum = #{snum,jdbcType=VARCHAR}
    AND Spassword = #{spassword,jdbcType=VARCHAR}
  </select>
</mapper>

注:什么时候必须加上 jdbcType

在 coding 的时候,有时候会发现,比如在 User.xml 中,不管是用 userId = #{userId} 还是 userId = #{userId, jdbcType = Integer},都没有问题。但是什么时候必须要加上 jdbcType 呢?

Mybatis 的官方文档是这样描述 jdbcType 的 :

The JDBC Type from the list of supported types that follows this table. The JDBC type is only required for nullable columns upon insert, update or delete. This is a JDBC requirement, not a MyBatis one. So even if you were coding JDBC directly, you’d need to specify this type - but only for nullable values.

意思是说,只有当将一个空值作用于插入、更新、删除操作时,jdbcType 才是必须的。这是 JDBC 的一个需求,并不是 MyBatis 的。所以即使你是直接编写 JDBC,当它是空的时候,你也一定要指定它的类型,其他情况不需要指定它的类型。

在 Stack Overflow 上,同样有这样的解释:

Most of the times you don’t need to specify the jdbcType as MyBatis is smart enough to figure out the type from the objects you are working with. But if you send your parameters to the MyBatis statement inside a HashMap, for example, and one of the parameters is null, MyBatis won’t be able to determine the type of the parameter by looking at the HashMap because the HashMap is just a generic container and null itself carries no type information. At that point it would be o good idea to provide the jdbcType so that switching the database implementation later on does not cause any issues with null values.

就是说,在大部分时候,我们不需要指定 jdbcType,因为 MyBatis 足够智能地可以辨别出对象的类型。

但是如果你传过来的参数是一个 HashMap,其中一个参数是空的,MyBatis 将不能通过 HashMap 来决定对象的类型。

因为 HashMap 是一个通用的容器并且如果它本身是空的话,将不会携带任何的类型信息。

所以最好的做法是,当值是空的时候去指定它的 jdbcType,这样在之后转换为 db 实现的时候就不会再引起任何问题了。

jdbcType 和 javaType 的对应关系

jdbcType javaType
CHAR String
VARCHAR String
LONGVARCHAR String
NUMERIC java.math.BigDecimal
DECIMAL java.math.BigDecimal
BIT boolean
BOOLEAN boolean
TINYINT byte
SMALLINT short
INTEGER int
BIGINT long
REAL float
FLOAT double
DOUBLE double
BINARY byte[]
VARBINARY byte[]
LONGVARBINARY byte[]
DATE java.sql.Date
TIME java.sql.Time
TIMESTAMP java.sql.Timestamp
CLOB Clob
BLOB Blob
ARRAY Array
OTHER
UNDEFINED
NVARCHAR
NCHAR
NCLOB
CURSOR
NULL