zoukankan      html  css  js  c++  java
  • mybatis学习系列三(部分)

    1 forearch_oracle下批量保存(47)

    oracle批量插入

       不支持values(),(),()方式

    1、多个insert放在begin-end里面

       begin

       insert into myemployeee(id,last_name,email,gender,dept_id) values

       (myemployeee_seq.nextval,#{emp.lastName,jdbcType=VARCHAR},#{emp.email,jdbcType=VARCHAR},

       insert into myemployeee(id,last_name,email,gender,dept_id) values

       (myemployeee_seq.nextval,#{emp.lastName,jdbcType=VARCHAR},#{emp.email,jdbcType=VARCHAR},

       end;

       #{emp.gender,jdbcType=VARCHAR},#{emp.deptId,jdbcType=INTEGER})

     2、利用中间表

       insert into employeee(id,last_name,email)

       select employeee_seq.nextval,lastName,email from (

        select 'test_a_01' lastName,'test_a_e1' email from dual

        union

        select 'test_a_02' lastName,'test_a_e2' email from dual

        union

        select 'test_a_03' lastName,'test_a_e3' email from dual

    方式一:

    <!-- oracle第一种方式 -->

       <foreach collection="emps" item="emp" open="begin" close="end;">

       insert into myemployeee(id,last_name,email,gender,dept_id)

       values

       (myemployeee_seq.nextval,#{emp.lastName,jdbcType=VARCHAR},#{emp.email,jdbcType=VARCHAR},

       #{emp.gender,jdbcType=VARCHAR},#{emp.deptId,jdbcType=INTEGER})

       </foreach>

    方式二:

    <!-- oracle第二种方式 -->

       insert into myemployeee(id,last_name,email,gender,dept_id)

       select employeee_seq.nextval,lastName,email,gender,deptId from

       <foreach collection="emps" item="emp" open="(" close=")" separator="union">

       select #{emp.lastName,jdbcType=VARCHAR} lastName,#{emp.email,jdbcType=VARCHAR} email,

       #{emp.gender,jdbcType=VARCHAR} gender,#{emp.deptId,jdbcType=VARCHAR} deptId

        from dual

       </foreach>

    2 动态sql-内置参数_parameter_databaseId(48)

    不只是方法传递过来的参数可以被判断,取值

    Mybatis还有2个默认内置参数:

    _parameter:代表整个参数

    单个参数:_parameter即这个参数

    多个参数:参数会被封装为一个map,_parameter代表该map

    _databaseId:如果配置了DatabaseIdProvider标签,_databaseId代表当前数据库别名(如oracle)

     <!-- 内置参数_databaseId和 _parameter

       selectEmployeeByInnerParameter(Employee employee);

      -->

      <select id="selectEmployeeByInnerParameter" resultType="com.mybatis.bean.Employee">

       <if test="_databaseId == 'oralce' ">

       select * from tbl_employeee

       <!-- <if test="_parameter !=null">

       where last_name= #{_parameter.lastName}

       </if> -->

       <if test="_parameter !=null">

       where last_name= #{lastName}

       </if>

       </if>

       <if test="_databaseId == 'mysql' ">

       select * from myemployeee 

       <if test="_parameter !=null">

       where last_name=#{_parameter.lastName}

       </if>

       </if>

      </select>

    3 动态sql-bind绑定(49)

    <if test="_databaseId == 'mysql' ">

       select * from myemployeee 

       <!-- like 查询

       方式一:$ 不安全

       where last_name like '%${lastName}%'

       方式二:# CONCAT

       where last_name like CONCAT('%',#{lastName},'%')

       方式三:bind,将值绑定到一个变量中,方便后来引用

       <bind name="_lastName" value="'%'+lastName+'%'"/>

       <if test="_parameter !=null">

       where last_name like #{_lastName}

       </if>

        -->

       <bind name="_lastName" value="'%'+lastName+'%'"/>

       <if test="_parameter !=null">

       where last_name like #{_lastName}

       </if>

       </if>

    4 动态sql-sql抽取可重用sql片段(50)

    1)定义sql片段

    <sql id="queryColumn">

       id,last_name,email,gender,dept_id

      </sql>

     

    2)使用

    select

       <include refid="queryColumn"></include>

        from myemployeee

     

     

    include中自定义属性及值,sql标签内即可使用

    注意:只能使用$,不能使用#

    select

       <include refid="queryColumn">

       <!-- 自定义属性及值 -->

       <property name="testColumn" value="test"/>

       </include>

        from myemployeee 

     

    <sql id="queryColumn">

       id,last_name,email,gender,dept_id,${testColumn}

      </sql>

     

    5 缓存-一级缓存(51-53)

    一级缓存:默认开启,sqlsession级别缓存(也称为本地缓存),查询的结果存放在map中

    二级缓存:手动开启和配置,基于namespace级别

     

    1)测试一级缓存

    EmployeeMapper mapper=session.getMapper(EmployeeMapper.class);

    List<Employee> emps=mapper.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps.toString());

    List<Employee> emps2=mapper.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps2.toString());

    System.out.println(emps2==emps); //为true

    实际只执行了一次sql语句,后面的查询从一级缓存获取

     

    一级缓存失效情况:

    1、sqlsession不同

    2、Sqlsession相同,查询条件不同(需要执行新sql)

    3、sqlsession相同,2次查询间执行了增删改操作(影响当前数据)

    4、sqlsession相同,手动清除了一级缓存

     

     

     

     

    1、sqlsession不同

     

    //一级缓存测试失效(非同一个sqlsession执行2sql

    EmployeeMapper mapper=session.getMapper(EmployeeMapper.class);

    List<Employee> emps=mapper.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps.toString());

    SqlSession session2 = sqlSessionFactory.openSession();//手动提交

    EmployeeMapper mapper2=session2.getMapper(EmployeeMapper.class);

    List<Employee> emps2=mapper2.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps2.toString());

    System.out.println(emps2==emps); //为false

     

    2、sqlsession相同,查询条件不同

    //一级缓存测试失效(情况2:同一个sqlsession,不同查询条件)

    EmployeeMapper mapper=session.getMapper(EmployeeMapper.class);

    List<Employee> emps=mapper.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps.toString());

    List<Employee> emps2=mapper.selectEmployeeByIds(Arrays.asList(1,2,3));

    System.out.println(emps2.toString());

    System.out.println(emps2==emps); //为false

     

    3、sqlsession相同,2次查询间执行了增删改操作(影响当前数据)

    //一级缓存测试失效(情况3:sqlsession相同,2次查询间执行了增删改操作(影响当前数据))

    EmployeeMapper mapper=session.getMapper(EmployeeMapper.class);

    List<Employee> emps=mapper.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps.toString());

    //更新操作

    int updateSize=mapper.updateEmp(new Employee(3,"test333","test3333@com.cm","女",1));

    List<Employee> emps2=mapper.selectEmployeeByIds(Arrays.asList(1,2,3));

    System.out.println(emps2.toString());

    System.out.println(emps2==emps); //为false

     

    4、sqlsession相同,手动清除了一级缓存

     

    //一级缓存测试失效(情况4:同一个sqlsession,清除了一级缓存)

    EmployeeMapper mapper=session.getMapper(EmployeeMapper.class);

    List<Employee> emps=mapper.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps.toString());

    session.clearCache();

    List<Employee> emps2=mapper.selectEmployeeByIds(Arrays.asList(1,2,3));

    System.out.println(emps2.toString());

    System.out.println(emps2==emps); //为false

     

     

    6 缓存-二级缓存(54-55)

    二级缓存(全局缓存),基于namespace级别缓存

    工作机制:

    1、一个会话查询一条数据,数据会被放在当前会话的一级缓存中。

    2、会话关闭,一级缓存中的数据会被保存到二级缓存中。

    3、sqlsession==employmapper==>employee

    Deptmapper===>dept

    不同namespace查出数据会放在自己对应的缓存map中

    查询的数据默认先放在一级缓存中,只有会话提交或关闭后,一级缓存中的数据会转移到二级缓存中

     

    使用:

    1)开启二级缓存配置

    默认开启,也可在mybatis-config.xml配置文件中设置

     

    <!-- 开启二级缓存,默认开启 -->

       <setting name="cacheEnabled" value="true"/>

     

    2)xml配置使用(namespace级别)

    Mapper中配置使用二级缓存

    <cache></cache>

     

    <!-- mapper中配置二级缓存

    eviction:回收策略,LRU,FIFO,SOFT,WEAK;默认LRU

    flushInterval:缓存刷新间隔(默认不清空),定位秒

    readOnly:是否只读,true/false,默认false

    true:mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据,

    mybatis为了加快获取速度,会直接将数据在缓存中的引用返回,不安全,速度快

    false:非只读,mybatis可能认为数据可能会被修改,mybatis会利用序列化&反序列化技术克隆数据,安全,速度慢

     -->

    <cache eviction="" flushInterval="" readOnly=""></cache>

     

     

    3)POJO需要实现序列化接口

     

     

    测试样例:

    1)mapper中配置

    <cache></cache>

    2)测试类

    //二级缓存测试

    EmployeeMapper mapper=session.getMapper(EmployeeMapper.class);

    List<Employee> emps=mapper.selectEmployeeByInnerParameter(new Employee(null,"addemps1","addemps1@qq.com","男",1));

    System.out.println(emps.toString());

    session.close();

    SqlSession session2 = sqlSessionFactory.openSession();//手动提交

    EmployeeMapper mapper2=session2.getMapper(EmployeeMapper.class);

    List<Employee> emps2=mapper2.selectEmployeeByIds(Arrays.asList(1,2,3));

    System.out.println(emps2.toString());

    System.out.println(emps2==emps); //为false

    session2.close();

     

    3)报错

    [com.mybatis.bean.Employee@2473b9ce, com.mybatis.bean.Employee@60438a68, com.mybatis.bean.Employee@140e5a13, com.mybatis.bean.Employee@3439f68d]

    Exception in thread "main" org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException: com.mybatis.bean.Employee

    at org.apache.ibatis.cache.decorators.SerializedCache.serialize(SerializedCache.java:102)

     

    Employee没有序列化,实现Serializable接口后

     

    再报错:

    false

    Exception in thread "main" org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException: com.mybatis.bean.MyDept

     

    MyDept没有序列化,实现Serializable接口

     

     

    4)输出结果

    [com.mybatis.bean.Employee@2473b9ce, com.mybatis.bean.Employee@60438a68, com.mybatis.bean.Employee@140e5a13, com.mybatis.bean.Employee@3439f68d]

    [com.mybatis.bean.Employee@29ba4338, com.mybatis.bean.Employee_$$_jvst385_0@7bb58ca3]

    false

     

    False是因为通过序列化拷贝的数据。

    如果不配置<cache>,则会发送2sql请求;

     

     

    7 缓存-二级缓存的设置(56)

    1)setting配置中

    <!-- 开启二级缓存,默认开启 -->

       <setting name="cacheEnabled" value="false"/>

     

    关闭二级缓存,但一级缓存未关闭;设置的是二级缓存

    2)每个select标签都有useCache=true,默认为truefalse为关闭;设置的是二级缓存。

    3)每个增删改包含标签:flushcache=true;默认为true;清空缓存(一级和二级缓存都清空

    4sqlsession.clearCache();清空一级缓存

    5localcachescope:本地缓存(本地会话)范围,一级缓存

     

     

    8缓存-原理图示(57 )

     

    9缓存-第三方缓存整合原理&ehcache适配器(58-59)

    引入ehcache-core缓存jar包,还有其他缓存包,可参考mybatis github网站

  • 相关阅读:
    实习一面+二面+三面面经
    内核协议栈2
    android之activity生命周期图
    gcc1
    实习一
    android之startActivityForResult
    KFS
    android之使用DDMS帮助开发
    设计模式——工厂模式
    博客备份工具(博主网)开发略谈
  • 原文地址:https://www.cnblogs.com/cslj2013/p/10389652.html
Copyright © 2011-2022 走看看