mybatis基础面试

mybatis基础面试

  1. mybatis查询数据输出结果为null,如何解决
 1.问题:可能是Java实体类的属性名和表中的字段名称不一致
      解决方法:
       1,查询出来的字段和你实体类中对应的属性名保持一致
       2.当进行单表简单查询时且返回值类型是基本类型时,一般尽量使用resultType;
       当进行表关联查询时,或者说xml中定义了相关的resultMap标签,那么就一般尽量使用resultMap;
    	resultType和resultMap不能同时使用。
  1. mybatis中,#{}和${}的区别
 "#{}是预编译处理,${}是字符替换
 在使用#{}时,mybatis会将SQL中的#{}替换成“?”,配合preparedStatement的set方法赋值,
这样可以有效的防止SQL注入,保证程序运行的安全"
  1. mybatis的分页方式
分页方式:逻辑分页和物理分页
逻辑分页:使用mybatis自带的rowBounds进行分页,它是一次性查询很多数据,然后在数据中再进行检索
物理分页:自己手写sql分页,或者使用分页插件pageHelper,去数据库查询指定条数的分页数据形式

  1. mybatis逻辑分页和物理分页的区别
逻辑分页是一次查询很多数据,然后再结果中检索分页的数据。
弊端:需要消耗大量的内存,有内存溢出的风险,对数据库压力较大

物理分页是从数据库查询指定条数的数据,弥补了一次性全部查出的所有数据的种种缺点
比如需要大量的内存,对数据库查询压力较大等问题
  1. mybatis分页插件的实现原理是什么
分页插件的基本原理是使用mybatis提供的插件接口,自定义插件,在插件的拦截方法内拦截带执行的SQL
然后重写SQL,根据dialect方言,添加对应的物理分页语句和物理分页参数

  1. mybatis如何编写一个自定义插件
    自定义插件的原理:
    mybatis自定义插件针对mybatis四大对象(Executor,StatementHandler,ParameterHandler,ResultSetHandler)进行拦截

    Executor:拦截内部执行器,它负责调用StatementHandler操作数据库,并把结果集通过ResultSetHandler进行自动映射,另外它还处理了二级缓存的操作;

    StatementHandler:拦截SQL语法构建的处理,它是mybatis直接和数据库执行SQL脚本的对象,另外它也实现了mybatis 的一级缓存
    
    ParameterHandler:拦截参数的处理
    
    ResultSetHandler:拦截结果集的处理

自定义插件的关键:

/**mybatis插件要实现interceptor接口,*/
public interface Interceptor(

    Object intercept(Invocation invocation) throws Throwable;

    Object plugin(Object target);

    void setProperties(Properties properties);
    
    }
    
/** setProperties方法是在mybatis进行配置插件的时候可以配置自定义相关属性;
	plugin方法是插件用于封装目标对象的,通过该方法我们可以返回目标对象本身,
	也可以返回一个它的代理,可以决定是否需要进行拦截进而决定要返回一个什么样的目标对象,官方示例:return Plugin.wrap(target,this);
	intercept方法就是要进行拦截的时候要执行的方法.
*/        

自定义插件实现

@Intercepts({@Signature(type=Executor.class.method="query",
args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})})
	public class TestInterceptor implements Interceptor{
    public Object intercept(Invocation invocation) throws Throwable{
    Object target=invocation.getTarget();//被代理对象
    Method method=invocation.getMethod();//代理方法
    Object[] args=invocation.getArgs();//方法参数
    //do something...  方法拦截前执行代码块
    Object result=invocation.proceed();    
    //do something...方法拦截后执行代码块
    return result;
    }

    public Object plugin(Object target){
    return Plugin.wrap(target,this);
    }
    
  1. mybatis的一级缓存和二级缓存
一级缓存:
    基于PerpetualCache的HashMap本地缓存,它的声明周期和SQLSession一致的,有多个SQLSession或者分布式的环境中数据库操作,可能会出现脏数据。
    当Session flush或close之后,该Session中的所有cache就将清空。
    默认一级缓存是开启的。

二级缓存:
    也是基于PerpetualCache的HashMap本地缓存,不同在于其存储作用域为Mapper级别的,如果多个SQLSession之间需要共享数据,则需要使用到二级缓存,并且二级缓存可自定义存储源,如E和Cache
    默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态)

开启二级缓存数据查询流程:
    二级缓存》一级缓存》数据库

缓存更新机制: 
    当某一个作用域(一级缓存Session/二级缓存Mapper)进行了增删改操作后,默认该作用域下所有select中的缓存将被clear
  1. mybatis有哪些执行器(Executor)
SimpleExecutor:每执行一次update或select就开启一个Statement对象,用完立刻关闭Statement对象;

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

BatchExecutor:执行update(没有select,jdbc批量处理不支持select),将所有SQL都添加到批处理中(addBatch()),等待统一执行(executeBatch()),
它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行了executeBatch()批处理,与jdbc批处理相同
  1. mybatis是否支持延迟加载,延迟加载的原理是什么
mybatis支持延迟加载,设置lazyLoadingEnabled=true即可

延迟加载的原理:
调用的时候触发加载,而不是初始化的时候就加载信息
(例如:调用a.getB().getName(),这时候发现a.getB()的值为null,此时会单独触发实现保存号的关联B对象的SQL,
先查询出来B,然后再调用a.setB(b),而这时候再调用a.getB().getName()就有值了,这就是延迟加载的基本原理)
  1. RowRounds是一次性查询全部的结果吗,为什么
RowRounds表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据
因为mybatis是对jdbc的封装,在jdbc驱动中有一个Fetch Size的配置,它规定了每次最多从数据库查询多少条数据,

假如你要查询更多数据,它会在你执行next()的时候,去查询更多的数据。
(就好比你去自动提款机取1w元,但取款机每次最多只能取2.5k,所以要取4次才能把钱取完。)

只对于jdbc来说,当你调用next()的时候会自动帮你完成查询工作,这样做的好处可以有效的防止内存溢出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值