MyBatis映射器总结

MyBatis映射器总结

Mybatis映射器xml配置包含如下标签:

  • select 查询语句,自定义参数返回结果集
  • insert 插入语句
  • update 更新语句
  • delete 删除语句
  • parameterMap 定义参数映射关系,不建议使用
  • sql 定义一段SQL,可以再其他部分引用
  • resultMap 结果集,提供映射规则
  • cache 给定命名空间的缓存配置
  • cache-ref 其他命名空间缓存配置的引用

1.select

1.1 select标签包含如下属性:

属性 说明 备注
id 它和Mybatis的命名空间组合起来是唯一的,提供MyBatis调用 若果命名空间和id结合起来不唯一,MyBatis会抛异常
parameterType 参数类型,可以给出类的全命名,也可以给出别名,但是别名必须是MyBatis内部定义或者自定义的 可以选择JavaBean、map等简单的参数传递给SQL
parameterMap 新版废弃的,不建议使用 --
resultType 定义类的全路径,在允许自动匹配的情况下,结果集将通过 JavaBean 的规范映射;或定义为 int、double、float、map 等参数;也可以使用别名,但是要符合别名规范,且不能和 resultMap时使用 常用的参数之 ,比如统计总条数时可以把它的值设置为 int
resultMap 它是映射集的引用,将执行强大的映射功能。我们可以使用resultType和 resultMap 其中的一个, resultMap 能提供自定义映射规则的机会 MyBatis最复杂的元素,可以配置映射规则、联级、typeHandler
flushCache 它的作用是在调用SQL后,是否要求MyBatis清空之前查询本地缓存和二级缓存 取值为布尔型,true/false默认值为false
userCache 启动二级缓存的开关,要求MyBatis将此次的结果缓存 取值为布尔型,true/false默认值为true
timeout 设置超时参数,超时后将抛出异常,单位为 秒 默认值是数据库厂商提供的JDBC驱动所设置的秒数
fetchSize 获取记录的总条数设定 默认值是数据库厂商提供的JDBC驱动所设置的条数
statementType 告诉MyBatis使用哪个JDBC的Statement工作,取值为STATEMENT(Statement)、PREPARED(PreparedStatement)、CALLABLE(CallableStatement) 默认为PREPARED
resultSetType 这是对 JDBC resultSet 接口而言,它的值包括FORWARD_ONLY (游标允许向前访问)、 SCROLL_SENSITIVE (双向滚动 ,但不及时更新,就是如果数据库里的数据修改过不在 re ultSet 中反映出来)、 SC ROLL INSENSITIVE (双向滚动,并及时跟踪数据库的更新,以便更改 re ultSet 中的数据) 默认值是数据库厂商提供的 JDBC 驱动所设置的
databaseId 结合setting的databaseIdProvider数据库厂商标识 支持不同的数据库sql
resultOrderd 这个设置仅适用于嵌套结果 select 语句 如果为 true ,就是假设包含了嵌套结果集或是分组了,当返回 个主结果行时,就不 能引用前面结果集了 。这就确保了在获取嵌套的结果集时不至于 导致内存不够用 取值为布尔型,true/false默认值为false
resultSets 适合于多个结果集的情况,它将列出执行 SQL 后每个结果集的名称,每个名称之间用逗号分隔 很少使用

1.2 自动映射和驼峰映射

在setting元素中提供了两个可以配置的选项:

  • autoMappingBehavior(SQL列名和属性名保持一致)
    • NONE,不进行自动映射
    • PARTIAL,默认值,只对没有嵌套结果集进行自动映射
    • FULL,对所有的结果集进行自动映射,包括嵌套结果集。
  • mapUnderscoreToCamelCase (true/false , user_name ===>> userName)

1.3 传递多个参数

  • map

    • 需要 parameterType="map"
    • 但是使用map不能限定其传递的数据类型
  • 使用@Param注解

    • 代码可读性大大提高
    • 不需要给出parameterType属性了,让MyBatis自动探索
  • JavaBean传递参数

    • 事先定义好POJO 如:User{ private String name;private Integer age}
    • 接口方法传值 selectByxxx(User user) ,同时parameterType="xxx.xxx.xxx.User"
  • 混合使用

    public Paging fidPageByUser(@Param("user") User user,@Param("page")PageParam pageParam);
    <select id="fidPageByUser" resultType="paging">
      select * from t_user 
        where user_name like 
        concat('%',#{user.name},'%')
        and age != #{user.age}
        limit #{page.start},#{page.limit}
    </select>

总结:

  • 使用 map传递参数导致了业务可读性的丧失,导致后续扩展和维护的困难,在实际
    的应用中要果断废弃这种方式。
  • 使用@Param 注解传递多个参数,受到参数个数 (n)的影响。当 你 <= 5 时, 这是最
    佳的传参方式,它比用 Java Bean 更好,因为它更加直观 n>5 时, 多个参数将
    给调用带来困难,此时不推荐使用它。
  • 当参数个数多于 5个时,建议使用 Java Bean 方式。
  • 对于使用混合参数的,要明确参数的合理性。

1.4 使用resultMap映射结果集

resultMap标签可以支持复杂的映射,如typeHandler、联级等。同时select标签也提供了resultMap属性将定义好的resultMap作为映射结果集。

2. insert/update

2.1 insert标签包含如下属性:

属性 描述 备注
id SQL编号,用于标识这条SQL 唯一,不然抛异常
parameterType 参数类型,同select 可以单个也可以多个
parameterMap 废弃 --
fushCache 是否刷新缓存,为true,插入时会刷新一、二级缓存 默认值 true,而select默认false
timeout 超时时间,单位 秒 --
statementType 告诉MyBatis使用哪个JDBC的Statement工作,取值为STATEMENT(Statement)、PREPARED(PreparedStatement)、CALLABLE(CallableStatement) 默认为PREPARED
useGeneratedKeys 是否启用JDBC的getDeneratedKeys方法来取出由数据库内部生成的主键。(如mysql的自增主键) 默认为 false
keyProperty 用来告诉系统,生成的主键放在哪个属性中。如果有多个就用,分割 默认值unset。不能和keyColumn连用。(仅对insert和update语句有用)
keyColumn 用来告诉系统,生成的主键放在哪个属性中。如果有多个就用,分割 不能和keyProperty连用。(仅对insert和update语句有用)
databaseId 不同数据库的不同语句 --

2.2 主键回填

<insert id="insertUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
    insert into t_user(user_name,user_age) values(#{userName},#{age})
</insert>

2.3 selectKey实现自定义主键

<insert id="insertUser" parameterType="user">
    <selectKey keyProperty="id" resultType="long" order="BEFORE">
        select if(max(id)=null,1,max(id)+3) from t_user
    </selectKey>
    insert into t_user(user_name,user_age) values(#{userName},#{age})
</insert>

3. SQL标签

sql标签的作用在于可以定义一条SQL的一部分,方便后面的SQL引用它,比如最典型的列名。通常在select、insert等语句中反复编译他们。

<sql id="userCols">
    id,user_name,user_age
</sql>
<select id="selectOneById" parameterType="long" resultMap="userMap">
    select <include refid="userCols" /> from t_user where id = #{id}
</select>
<insert id="insertUser" parameterType="user">
    insert into t_user(<include refid="userCols" />) values(#{id},#{userName},#{userAge})
</insert>

传递变量给sql标签:

<sql id="userCols">
    ${alias}.id,${alias}.user_name,${alias}.user_age
</sql>
<select id="selectOneById" parameterType="long" resultMap="userMap">
    select 
    <include refid="userCols" >
        <property name="alias" value="r" />
    </include>
    from t_user r where id = #{id}
</select>

4. 参数

#{userName,typeHandler=com.example.mybatis.StringTypeHandler},#{userAge}
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler} 
#{width , javaType=double , jdbcType=NUMERIC, numericScale=2} 
  • 存储过程支持

    #{id,mode=IN}
    #{userName,mode=OUT}
    #{age,mode=INOUT}
  • 特殊字符串的替换和处理

  • 接口参数可以传递子类实例

    insert(A a); B extends A; ==> insert(b);

5. resultMap

resultMap的作用是定义映射规则、联级更新、定制类型转换器等。但是只支持resultMap的查询。

5.1 resultMap元素的构成

  • resultMap元素的子元素:

    <resultMap>
      <constructor> <!--用于配置构造方法,不存在没有参数的构造方法的情况-->
          <idArg />
            <arg />
        </constructor>
        <id />
        <result />
        <association />
        <collection />
        <discriminator>
          <case />
        </discriminator>
    </resultMap>
  • result元素和idArg元素的属性

    • property POJO的属性
    • column 对应的是SQL的lie
    • javaType 配置java的类型
    • jdbcType 配置数据库的类型
    • typeHandler 类型处理器

5.2 使用map存储结果集

一般而言,任何select语句都可以使用map存储:

<select id="select" parameterType="string" resultType="map">
    select xxxxxxxxxxx ...
</select>

map原则上是可以匹配所有的结果集,但是可读性下降。更多推荐POJO的方式。

5.3 使用POJO存储结果集

使用resultMap映射了。

5.4 联级

mybatis的联级分为3种:

  • 鉴别器 discriminator
  • 一对一 association
  • 一对多 collection

5.5 N+1问题与延迟加载

假设现在有 个关联关系完成了级联,那么只要再加入 个关联关系,就变成了 N+1个级联,所有的级联 SQL 会被执行,显然会有很多并不是我们关心的数据被取出,这样会造成很大的资源浪费,这就是 N+1问题,尤其是在那些需要高性能的互联网系统中,这往往是不被允许的。

所以有了延迟加载的功能,一开始只加载需要的部分,当我们需要时对应的记录才通过SQL取出来。

配置项 作用 配置选项说明 默认值
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。在特定关联关系中,可通过设置fetchType属性来覆盖该项的开关状态。 true|false false
aggressiveLazyLoading 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,则每种属性按需加载。 true|false 版本3.41(包含)之前是true,之后为false

6. 缓存

mybatis中允许使用缓存,缓存一般都存放置在高速读/写的存储器上。

  • 一级缓存,是在SqlSession上的缓存
  • 二级缓存,是在SqlSessionFactory上的缓存 <cache />
  • 缓存配置项、自定义和引用
上一篇:MyBatis之ResultMap-自定义结果映射


下一篇:使用代码上传文件示例