mybatis复习笔记----关于一些需记忆的点

POINT-一些点

一、sql插入后,返回自增主键值
mybatis也是利用statement.getGenreatedKeys()。

属性:
useGeneratedKeys="true"----使用自增主键获取主键值策略
keyProperty----指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性-->
例如:
<insert id="addEmp" parameterType="com.atguigy.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id">
    insert into tbl_employee(last_name,email,gender)values(#{lastName} ,#{emai1} ,#{gender})
</insert>

oracle不支持自增,但使用序列来模拟自增。

每次插入的数据的主键是从序列中拿到的值;如何获取到这个值;
<insert id="addEmp" databaseId="oracle">
      <!- -
            keyProperty:查出的主键值封装给javaBean的哪个属性order="BEFORE":当前s.ql在插入sgl之前运行
            resultType:查出的数据的返回值类型
      -->
      <selectKey keyProperty="id" order="BEFORE"resultType="Integer">
            <! --编写查询主键的s.gl语句-->
            select EMPLOYEES_SEQ.nextval from dual
      </selectkey>
      <!--插入时的主键是从序列中拿到的   其实也可以直接在sql里写从序列里取值,即#{id}替换为employees_seq.nextval –->
      insert into employees(EMPLOYEE_ID,LAST_NAME ,EMAIL)values(#{id} ,#{lastName} ,#{email})
</insert>

二、对于接口方法中传递参数处理

  • @Param("")来指定参数对应的值
    当接口方法传递多个参数时,对应mapper.xml默认使用map存储,key=param1...paramn表示,value=参数值,所以在sql中通过#{}取值时要通过param1...paramn来取
    若想指定参数的key需要在接口参数前添加@Param("xxx")来指定。
    即接口中传递过来的参数可以是pojo也可以是一个map,因为最后都是转为一个map

To: 如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO (Transfer object)数据传输对象

明确即接口对应.xml配置sql文件可传递:pojo、map、To(数据传输对象)

  • 参数封装
    对于传过来的collectio类型,或数组,若没有@Param注解表示,需要用list来取值,因为也是封装成一个map,但是key=list
例如:
public Employee getEmpById(List<Integer> ids);
取值:取出第一个id的值:错误:#{param1[0]},#{ids[0]}都是错的  正确:#{list[0]},

三、关于#{}与${}取值时的预编译与拼接
#{}:是以预编译的形式,将参数设置到sql语句中;Preparedstatement:防止sql注入
${}:取出的值直接拼装在sql语句中;会有安全问题;
大多情况下,我们去参数的值都应该去使用#{};
原生jdbc不支持占位符的地方我们就可以使用${}进行取值,比如按照年份分表拆分,分表、排序等;

select *from ${year}_salary where XXX3
select * from tbl_employee order by $if_name} ${order}

四、#{}更丰富的用法:
规定参数的一些规则:

javaType、jdbcType. mode(存储过程)、numericScale、
resultMap、typeHandler、jdbcTypeName、expression(未来准备支持的功能)

jdbcType通常需要在某种特定的条件下被设置:
在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错)﹔
JdbcType OTHER=无效的类型,因为mybatis对所有的nul1都映射的是原生Jdbc的OTHER类型,oracle不能处理。
由于全局配置中:jdbcTypeForNull=OTHER; oracle不支持;可通过以下两种方法解决。

1、#{emai1,jdbcType=OTHER];
2、jdbc TlypeForNu11=NULLl

五、resultType:如果返回的是一个集合,要写集合中存储元素的类型,而不是list类型

六、可以在接口方法中通过@MapKey("xxx")来指定接口对应.xml配置文件对应方法的sql语句返回类型为map时用什么来作为map的键

七、多个数据一起插入,mysql支持values后面跟‘,’分割的多个‘()’。如:insert into student values(101,"xhangsan"),(102,"lisi"),而oracle则不支持。
----解决oracle多数据插入:
1--多个insert语句放在begin ... end 里面

begin
    insert into employees(employee_id,last_name , email)
    values(employees_seq.nextval, 'test_001' , 'test_001@xiaoai.com');
    insert into employees (employee_id,last_name , email)
    values(employees_seq.nextval, 'test_002' , 'test_0e02@xiaoai.com');
end;
例如mabatis使用:
<insert id="addEmps" databaseId="oracLe">
    <!-- oracle第一种批量方式-->
    <foreach collection="emps" item= "emp" open="begin" close="end">
        insert into employees(employee_id,1ast_name, email)
        values(employees_seq.nextval,#{emp. lastName},#{emp.emai1}
    </foreach>
</insert>

2--利用中间表

例如sql语句:
insert into employees(employee_id, last_name, email)
      select employees_seq.nextval, lastName , email from(
            select 'test_a_01', lastName, 'test_a_eO1’ email from dual
            union
            select 'test_a_02', lastName, 'test_a_e02' email from dual
            union
            select 'test_a_03', lastName, 'test_a_e03' email from dual
      )
例如mabatis使用:
<insert id="addEmps" databaseId="oracLe">
    <! -- oracle第二种批量方式-->
    insert into employees(employee_id,last_name, email)
        <foreach collection="emps " item="emp" separator="union"
        open=" select employees_seq.nextva1,lastName , email from("
        close=")">
            select #{emp.lastName} lastName, #{emp.email} email from dual
        </foreach>
</insert>

八、两个默认内置参数

_parameter:代表整个参数
    单个参数:_parameter就是这个参数
    多个参数:参数会被封装为一个map:_parameter就是代表这个map
_databaseId:如果配置了databaseIdProvider标签。
    _databaseId就是代表当前数据库的别名|

例如使用:
当相同数据在不同数据库时,判断当前使用什么数据库对应查询什么表
<select id="getEmpsTestInnerParameter" resultType="com.xiaoai.employee">
    <if test="_databaseId=='mysqL'">
        select * from tbl_employee
    </if>
    <if test="_databaseld=='oracle'">
        select * from employees
    </if>
</ select>

缓存

一、一级缓存(本地缓存)
一级缓存是一直开启的,缓存即SqlSession级别的一个map

一级缓存失效情况:(即没有使用到当前一级缓存的情况,需要再向数据库发出查询)
1--sqlsession不同
2--sqlsession相同,查询条件不同(即当前一级缓存中还没有要查询的数据>
3--sqlsession相同,查询条件相同,但是两次查询之间进行过增删改操作(怕增删改对数据进行了更改)。
4--手动清除了一级缓存,即通过sqlsession.clearCache()清除缓存;  .clearCache()只清除一级缓存,增删改时一、二级缓存都会清除。

二、二级缓存(全局缓存)
常用数据放到二级缓存中,基于namespace级别的缓存,一个namespace对应一个二级缓存。

工作机制
1、一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
2、如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容。

三、缓存设置
在接口对应.xml配置文件中通过【cache】标签设置

<cache eviction="" flushInterval="" readOnly="" size="" type=""></cache>
属性说明:
1--eviction:缓仔的回收策略:当缓存慢了以后,需要删除一些数据,会根据设置的策略进行删除 默认的是LRU。
      LRU 最近最少使用的:移除最长时间不被使用的对象。
      FIFO 先进先出:按对象进入缓存的顺序来移除它们。
      SOFT 软引用:移除基于垃圾回收器状态和软引用规则的对象。
      WEAK 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
2--flushInterval:缓存刷新间隔 缓存多长时间清空一次,默认不清空,设置一个毫秒值
3--readOnly:是否只读:
      true:只读; mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。 mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
      false:非只读:mybatis觉得获取的数据可能会被修改。 mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速席慢|
4--size:缓存存放多少元素;
5--type="":指定自定义缓存的全类名;实现Cache接口即可;

四、二级缓存使用
查出的数据默认放在一级缓存中,只有当sqlsession会话提交或者关闭后数据才会转移到二级缓存中。但前提是二级缓存开启了。

二级缓存的使用:
1--让Mybatis框架支持二级缓存(在主配置文件中配置)
    <settings> 
        <!-- 开启二级缓存的支持 -->  
        <setting name="cacheEnabled" value="true"/> 
    </settings> 
2--让当前接口方法的.xml映射文件支持二级缓存(在接口对应配置文件中配置)
    <mapper namespace="com.itheima.dao.IUserDao">  
        <!-- 开启二级缓存的支持 -->  
        <cache></cache> 
    </mapper>
3--让当前操作支持二级缓存(在select等操作标签中配置)
    <select id="findById" resultType="user" parameterType="int" useCache="true">  
        select * from user where id = #{uid} 
    </select>
posted @ 2020-11-29 17:54  小艾影  阅读(142)  评论(0编辑  收藏  举报