面试笔录---mybatis

1.mybatis是什么:

官网中给到的定义是这样的:
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
概念中有两个关键点:

(1)支持定制化sql和存储过程,避免了几乎所有的JDBC代码。
(2)实现了高级映射,避免了手动设置参数和获取结果集。

2.mybatis干了些什么:

(1)直接调用接口方法就可以实现语句的查询:

  • 通过配置文件构建sqlsessionfactory
  • 通过sqlsessionfactory获取sqlsession,sqlsession相当于传统的connection
  • 通过sqlsession获取Mapper映射
  • 通过mapper映射来执行sql语句,并返回结果集到javabean中

(2)如何实现查询参数和结果集与POJOs之间的映射?

  •  在PreparedStatementHandler中的query()方法中,是用ResultSetHandler来完成结果集的映射的。
  • Mybatis中只提供了一个ResultSetHandler的实现,那就是DefaultResultSetHandler

(3)数据库字段类型和java字段类型之间如何实现映射?是否支持扩展,如果需要自定义类型处理,应该怎么实现?

  • 通过xml文件中的mapper标签,命名空间nameSpace="你的实体类",再通过result标签实现实体类属性和数据库字段一一对应实现映射,其中property代表实体类属性,column代表数据库字段
  •  (1).自定义类型处理器实现TypeHandler接口,代码如下,这里的Strings是我自定义的字符串类型,不提倡如此使用;
    public class StringsTypeHandler implements TypeHandler<Strings> {
        @Override
        public void setParameter(PreparedStatement ps, int i, Strings parameter, JdbcType jdbcType) throws SQLException {
            System.out.println(jdbcType);
            if (parameter != null && StringUtils.isNotEmpty(parameter.toString())) {
                //加密
                String value = CodecUtil.encodeBASE64(parameter.toString());
                ps.setString(i, value);
            }
        }
     
        @Override
        public Strings getResult(ResultSet rs, String columnName) throws SQLException {
            String value = rs.getString(columnName);
            if (StringUtils.isNotEmpty(value)) {
                //解密
                value = CodecUtil.decodeBASE64(value);
            }
            return new Strings(value);
        }
     
        @Override
        public Strings getResult(ResultSet rs, int columnIndex) throws SQLException {
            String value = rs.getString(columnIndex);
            if (StringUtils.isNotEmpty(value)) {
                //解密
                value = CodecUtil.decodeBASE64(value);
            }
            return new Strings(value);
        }
     
        @Override
        public Strings getResult(CallableStatement cs, int columnIndex) throws SQLException {
            String value = cs.getString(columnIndex);
            if (StringUtils.isNotEmpty(value)) {
                //解密
                value = CodecUtil.decodeBASE64(value);
            }
            return new Strings(value);
        }
    }
    (2).在mybatis-config文件中配置
    	<typeHandlers>
    		<typeHandler javaType="com.jrq.core.encrypt.Strings" handler="com.jrq.core.encrypt.StringsTypeHandler"/>
    	</typeHandlers>

    Strings对应Java类型,StringsTypeHandler对应类型处理器

    现在JavaBean里所有的Strings类型都会被StringsTypeHandler处理

(4)如何自定义插件,插件的实现原理?

  • MyBatis中的四大对象
    在编写自定义拦截器之前,我们先来简单介绍一下MyBatis内部其中的四大对象的作用以及其创建过程。

    Executor:该对象主要是用来执行我们的sql语句的。

    StatementHandler:该对象主要是用来预编译我们的sq语句l,将输入参数用问号占位符的形式替换。

    ParameterHandler:该对象主要是将参数设置进我们预编好的sql语句。

    ResultSetHandler:该对象主要是处理结果集映射。

  • 自定义插件拦截器的步骤:1创建一个拦截器类实现Interceptor,实现里面的方法。2为这个拦截器注册方法签名,这个方法签名主要是来告诉mybatis这个拦截器类是用来拦截哪个类下的哪个方法的。3将编写好的拦截器类注册到mybatis的全局配置文件中。

  • MyBatis的四大对象的创建过程中都不是直接返回的,而是进行 interceptorChain.pluginAll()进行包装后返回的。
    MyBatis框架提供的Interceptor接口只能用来拦截这四大对象下的方法。
    编写好自定义拦截器后记得将其设置到全局配置文件中。
    四大对象:Executor、StatementHandler、ParameterHandler、ResultSetHandler

(5)有哪些动态sql关键字,如何使用?

  •  if标签一般用于非空验证,如上例,若id为空,if标签里的代码,将不会执行,反之,则会执行。

  • choose(when,otherwise)标签相当于switch(case,default) ,如上例,若title 为空,when标签里的代码,将不会执行,默认执行otherwise标签里面的代码。
  • trim(where,set)标签:
    <select id="queryBy" resultType="com.scme.pojo.User" parameterType="com.scme.pojo.User">
                     select * from user 
                     <where>
                             <if test="username!=null and password!=null">
                                 and username=#{username} and password=#{password}
                             </if>
                     </where>
    </select>

    假设上例传入的username,password不为空,代码就可以运行成功!但朋友们可能有疑问了,实际上执行的sql语句是什么呢?其实,sql为:select * from user

     where username=? and password=?  朋友们是否发现,where标签代替了sql中where关键字,但if中的and不见了。其实where标签可以自动去除是“AND”或“OR”开头的sql中的“AND”或“OR”关键字

  • set标签功能和where标签差不多,set标签代替了sql中set关键字,set标签可以自动去除sql中的多余的“,”

  • foreach标签:foreach标签实现批量删除,直接上代码

    <delete id="batchDelete" parameterType="java.lang.String">
      delete from user
      where id in
      <foreach item="id" index="index" collection="list"
          open="(" separator="," close=")">
            #{id}
      </foreach>
    </delete >

    foreach标签可迭代任何对象(如列表、集合等)和任何的字典或者数组对象传递给foreach作为集合参数,当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。collection标签可以填('list','array','map')。

    foreach元素的属性主要有 item,index,collection,open,separator,close。

    item表示集合中每一个元素进行迭代时的别名;

    index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置;

    open表示该语句以什么开始,

    separator表示在每次进行迭代之间以什么符号作为分隔符;

    close表示以什么结束。

(6)mybatis缓存原理,一级缓存和二级缓存的区别?如何实现一二级缓存?

  • Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。 
    也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中; 
    第二次以后是直接去缓存中取。 
    当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。

    一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。 
    如果需要更改一级缓存的范围,可以在Mybatis的配置文件中,在下通过localCacheScope指定。

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

    建议不需要修改

    需要注意的是 
    当Mybatis整合Spring后,直接通过Spring注入Mapper的形式,如果不是在同一个事务中每个Mapper的每次查询操作都对应一个全新的SqlSession实例,这个时候就不会有一级缓存的命中,但是在同一个事务中时共用的是同一个SqlSession。 
    如有需要可以启用二级缓存。

  • Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。

    二级缓存是默认启用的(要生效需要对每个Mapper进行配置),如想取消,则可以通过Mybatis配置文件中的元素下的子元素来指定cacheEnabled为false。

  • cacheEnabled默认是启用的,只有在该值为true的时候,底层使用的Executor才是支持二级缓存的CachingExecutor。具体可参考Mybatis的核心配置类org.apache.ibatis.session.Configuration的newExecutor方法实现。 
    可以通过源码看看
     

  • 10
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值