1 Star 1 Fork 0

lagou-ch / IPersistence

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

[TOC]

mybatis常见问题

实体类的属性和表的字段名称不一致,怎么办?

  • 查询的sql语句中,定义字段的别名,此别名和实体的属性名一致就行

  • 通过<resultMap>来映射字段名称和实体属性名称的一一对应的关系

如何获取自动生成的(主)键值?

  • 按照mysql数据库的话,按照以下思路,关键字:LAST_INSERT_ID,获取插入之后ID值

    <selectKey keyProperty="id" order="AFTER" resultType="int">
                select LAST_INSERT_ID()
    </selectKey>

在mapper中如何传递多个参数?

  • 第一种:使用占位符的思想

    • 在映射文件中使用#{0},#{1}代表传递进来的第几个参数

      <select id="selectUser"resultMap="resultMap">  
          select * from t_user  where user_name = #{0} and user_area=#{1}  
      </select>
    • 使用@param注解

      public user selectUser(@param(username) string username);
  • 第二种:使用map的方式

    Map<String, Object> map = new HashMap();
    map.put("start", start);
    map.put("end", end);
    return sqlSession.selectList("user.selectUser", map);

Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理?

  • 作用
    • Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能
  • 类型
    • trim|where|set|foreach|if|choose|when|otherwise|bind
  • 原理
    • 使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能

Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

  • 分析
    • Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false
  • 原理
    • 它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用user.getProject().getName(),拦截器invoke()方法发现user.getProject()是null值,那么就会单独发送事先保存好的查询关联Project对象的sql,把Project查询上来,然后调用user.setProject(project),于是user的对象project属性就有值了,接着完成user.getProject().getName()方法的调用。 这就是延迟加载的基本原理,也就是直到用到的时候才会去加载,不会完成初始化就加载出来。

Mybatis都有哪些Executor执行器?它们之间的区别是什么?

Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。

  • SimpleExecutor

    每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

  • ReuseExecutor

    执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。

  • BatchExecutor

    执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

以上的这些Executor的作用范围都严格控制在SqlSession生命周期范围内

简述下Mybatis的一级、二级缓存(分别从存储结构、范围、失效场景。三个方面来作答)?

  • 存储结构

    • 一级:mybatis的一级缓存是SqlSession级别的缓存,在操作数据库的时候需要先创建SqlSession会话对象,在对象中有一个HashMap用于存储缓存数据,此HashMap是当前会话对象私有的,别的SqlSession会话对象无法访问。
    • 二级:二级缓存与一级缓存其机制相同,默认是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache,Redis。
  • 范围

    • 一级:一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。 也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。
    • 二级:二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置开启二级缓存,不过不建议开启。
  • 失效场景

    • 一级:当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。这里注意,清空的缓存,只是当前私有线程下独享的缓存,一级缓存的范围有SESSIONSTATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。

      <setting name="localCacheScope" value="STATEMENT"/>

    • 二级:和一级缓存一样,存在增删改的操作,当进行事务的提交时,会将缓存清空,但是需要注意的是,这里清空的是同一namespace下的缓存,还就执行缓存的clear操作做也会清空缓存,实质上是对所查找key对应的value将其置为null,而非将彻底删除缓存数据。

      tips

      二级缓存,建议在 SQL 映射文件中添加配置:

      <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

      这个语句的效果如下:

      • 映射语句文件中的所有 select 语句将会被缓存。

      • 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。

      • 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。

      • 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。

      • 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。

      • 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

      使用二级缓存容易出现脏读,建议避免使用二级缓存,在业务层使用可控制的缓存代替更好

空文件

简介

自定义持久层框架-mybatis 展开 收起
Java
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/lagou-ch/IPersistence.git
git@gitee.com:lagou-ch/IPersistence.git
lagou-ch
IPersistence
IPersistence
master

搜索帮助