转载

MyBatis入门小结

MyBatis 入门小结

MyBatis配置

为了使用 MyBatis ,我们需要需要完成以下步骤:

SqlSessionFactory
sqlSession
sqlSession
  1. Mapper接口与XML映射文件绑定,没有实现类,是mybatis为其生成的代理对象
  2. sqlSession是与数据库的一次会话,从而是非线程安全的

两个配置文件

MyBatis 中有两个主要的配置文件:

  1. 全局配置文件:用来配置全局属性,包含全局设置、数据库、事务、插件、映射文件的位置

    • 开启驼峰转换:驼峰转化 用于结果集的映射 (数据库物理字段到实体属性转化),而不是SQL语句中的字段【SQL语句中的查询字段依然是使用物理表中的字段与 JPA 有很大的不同】
    • 别名转换:预设别名【string int long double float list】
  2. 映射文件:主要用来配置SQL编写。

映射文件

  1. namespace:对应Mapper接口的全类名
  2. <select> :查询SQL

    id
    resultType
    databaseId
    

这里面的SQL,字段与物理表中的字段保持一致,参数名与属性保持一致【JSP取对象】

增删改的返回值会帮你自动封装成Integer,Long或者Boolean,只需要在Mapper接口中声明即可【增删改中也没有resultType】

  1. 主键的获取:

    1. <insert useGeneratedKeys="true" keyProperty="id">

      useGeneratedKeys
      keyProperty
      
    2. 使用 <selectKey> 编写查找主键的值

      • keyProperty :
      • order :有 beforeafter 【在该SQL之前插入还是之后】
      • resultType :指定ID的类型
  2. 参数:

    1. 单个简单基本参数:名字随便,不用做额外处理
    2. 单个POJO类型:其中的属性会被自动封装成Map的Key和Value
    3. 多个参数会被封装成Map符号 # 是从Map中取值,默认key是param1,param2...【使用注解 @Param 来指定Key】
    4. 单个参数是List、Set、数组,同样会被封装成Map【List的Key是#{list},数组是#{array}】【#{list[0]}】
  3. $#

    $
    #
    
  4. 使用#{key,javaType=,jdbcType }

返回值

  1. 放回List类型:直接填写简单类型

    • <select resultType="EmployeeEntity">
  2. 放回Map类型:

    • 单条记录封装: <select resultType="map"> 【查到了一个数据】
    • 多条记录封装: <select resultType="EmployeeEntity"> + @MapKey("propertyName") 【查到了多个数据】

resultMap

resultMap 用于自定义结果集映射封装。【建议使用 resultMap 将所有的列都写上!】

1. `<association>`:
<resultMap id="" type="EmployeeEntity">
        
        <id property="id" column="id"/>
    
        <result property="" column=""></result>

         <!-- 
            分布查询:延迟加载需要额外配置:
                lazyLoadingEnable: 是否激活延迟加载【所有的关联查询都将延迟加载】
                aggressiveLazyLoading: 如果开启的话只要有一个懒加载属性被加载,则该对象中的所有懒加载属性都将被加载,否则就按需加载
            <association property="dept" select="DeptMapper.getDeptById" column="dept_id" fetchType="lazy"/> 
            其中`column={keyName=ColumnName}`【keyName】是对方SQL中的#{xxx}
        -->
        <association property="" javaType=""> 
            <id property="" column=""></id>
            <result property="" column=""></result>
        </association>

        <collection property="" ofType="">
            <id></id>
            <result  property="" column=""></result>
        </collection>

    </resultMap>

动态SQL

  1. <if test="条件"> :test的判断表达式是使用OGNL表达式【】
<if test="aclId != null and aclId !='' and aclId.trim() != ''">
                
    </if>
  1. <where> :自动加上 where + 只能够去掉 开头AND
<where>
        <if test="name != null and name !=''">
            AND name like #{name}
        </if>
         <if test="name != null">
            AND age = #{age}
        </if>
    </where>
  1. <trim> : 字符串截取

    <trim>
    
<trim prefix="" prefixOverrides="" suffix="" suffixOverrides="">
        <if test="name != null and name !=''">
            AND name like #{name}
        </if>
        <if test="name != null">
            AND age = #{age}
        </if>
</trim>
  1. <choose> :
<choose>
        <when test="aclId">
            name = #{name}
        </when>

        <when test="aclId">
            last_name = #{lastName}
        </when>
        <otherwise>
            sex = #{sex}
        </otherwise>
    </choose>
  1. <set> :自动添加 set 字句 + 去掉最后的逗号
<update id="updateById">
        update  t_employee
                <set>
                    <if test="name != null">
                        name = #{name},
                    </if>

                    <if test="name != null">
                        age = #{age},
                    </if>
                </set>
    </update>
  1. <foreach>

    • collection:传入的参数
    • item:定义迭代变量
    • open:拼接结果的增加前缀
    • close:拼接结果的增加后缀
    • separator:迭代结果的类似join()的分隔符
<select>
    select * from t_employee e where e.id in
        <foreach collection="employeeList" item="one" open="(" separator="," close=")" index="i">
            #{id}
        </foreach>
</select>

<bind><sql>

  1. <bind>: 将OGNL表达式绑定到一个变量上 <bind name="_valName" value="Math.PI">
  2. <sql> + <include> :include还可以自定义一些属性,可以在 <sql> 中使用 ${} 进行访问

缓存

Mybatis 将缓存分为两级缓存:

* 一级缓存:sqlSession级别缓存
    * 查出数据之后,将会自动放入一级缓存中

* 二级缓存:Mapper级别缓存【本质是基于namespace的】,每一个Mapper都维护自己缓存
    * 二级缓存默认**不开启**的,需要手动配置,配置之后将会查询结果将会放入二级缓存【**不同的namespace中**】中

一次查询:先查询二级缓存,二级缓存中没有再到一级缓存中,如果一级缓存中没有则到数据库中查找

二级缓存配置

开启二级缓存需要完成下列的三步:

1. 全局配置文件:配置`cacheEnabled`,该属性设置二级缓存【只能设置二级缓存】
2. `Mapper.xml`:添加标签`<cache>`
    * `eviction`:缓存回收策略
    * `flushInterval`:多久清空一次
    * `readOnly`:是否只读。
        * 如果设置只读:则Mybatis会直接将缓存的应用给用户
        * 如果设置非只读:则先克隆缓存,然后再交给用户克隆之后的数据
    * `size`:缓存中可以放多少个元素
    * `type`:指定自定义缓存的全类名【实现Mybatis的`Cache`接口】
3. 缓存的数据实现序列化接口

缓存注意事项

缓存放入策略

查询结果先放入一级缓存中, 会话关闭 之后,将会话中的缓存放入二级缓存中

缓存失效:

一级缓存:
    * 增删改:一级缓存失效
    * 手动清除一级缓存:`opession.clearCache()`会清除二级缓存
二级缓存:
    * `select`标签的`useCache`:关闭二级缓存
    * 增删改:会清空缓存
    * 增删改标签的`flushCache`:设置`true`将会清空一级缓存,也会清除二级缓存【`select`标签的默认是false】
    * `openSession.clear()`不会清除二级缓存
`localCacheScope`:本地缓存作用域设置STETAMENT会禁用一级缓存。

第三方缓存整合

使用第三方缓存可使用如下的一种:

<cache type="缓存类型全类名">
<cache-ref="命名空间">
原文  https://segmentfault.com/a/1190000022454941
正文到此结束
Loading...