Mybatis的几道面试题

1.Mybatis和Hibernate有什么区别?

Hibernate是一个ORM框架,它将sql语句尽可能进行了封装,可以节省很多代码,提高效率。

而Mybatis则是半ORM框架,使用Mybatis的时候需要我们手动地去书写sql语句,相比于Hibernate,它的工作更加繁琐。但是同时这也是它的优点,因为我们可以手动地去严格控制sql语句执行性能,灵活度更高。

2.#{}和${}的区别是什么?

#{}是预编译处理,Mybatis遇到它的时候,会将它替换为“?”,然后调用PreparedStatement的set()方法进行填充

${}是字符串拼接,所以使用它可能会有SQL注入的情况发生。

所以一般来说还是用#{}好一点。

3.当实体类的属性名和表中的字段名不一致怎么办?

方法1:在查询的sql语句中直接定义这个字段的别名,将别名设置为和实体类的属性名一致

方法2:使用ResultMap,来实现一个数据库字段于实体类属性名的一个映射,

4.Dao接口的工作原理?

Dao接口中的方法之所以可以被直接调用,其实是使用动态代理的设计模式。也就是说,我们获得的Dao接口对象其实准确来说并不是接口对象,而是一个Proxy代理类对象,所以说,其实接口方法的调用都会被拦截下来,然后去执行代理类中invoke()方法

invoke()方法的执行,首先它会通过反射获取调用方法的全限定名,也就是包名+类名,通过这个全限定名,可以唯一定位一个MapperStatement对象,那么每一个MapperStatement对象都对应着Mapper文件的比如说 这样的数据库操作标签。所以真正对数据库的操作就是在这里进行的,这个对象最终会调用jdbc进行真正的数据库访问,然后将执行结果写入缓存中,然后封装成POJO对象进行返回。

这就是Dao接口的工作原理。

ps:由此可以看出,Dao接口方法是不允许重载的,因为是通过包名+类名来定位MapperStatement对象的,而若方法重载,那它们的全限定名就是相同了,那么在获取MapperStatement对象的这个逻辑上就会发生错误。

5.Mybatis是否支持延时加载(懒加载)?

延时加载就是按需加载,就是说只有当数据被访问到的时候才会当场进行加载,这样可以节省下资源。

在Mybatis中,如果设置开启了延时加载,如果在Mapper文件的ResultMap标签中如果出现了association或者collection这样的一对一或者一对多的映射关系,就会支持延时加载。

它的原理就是使用CGLIB创建目标对象的代理对象,当调用目标方法时就会被拦截下来,进入代理对象的invoke()方法中,此时如果发现方法请求的资源是空的,此时就要去访问数据库进行查询操作,把结果加载进去之后再返回。

(不知是Mybatis,很多框架的延时加载基本都是这么一个逻辑)

6.Mybatis的一级二级缓存?

Mybatis的一级缓存是默认开启,并且无法关闭,一级缓存是SqlSession级别的,也就是说不同的SqlSession内的缓存结果是互不相同的。如果一个SqlSession实例关闭了,那么它的缓存也会随之被清除;同时如果对相关的资源进行增删改操作,那么对应的缓存也会被清除。

二级缓存和一级缓存的机制相似,区别就是,二级缓存是多个SqlSession共享的,所以SqlSession关闭之后,缓存依然存在,直到整个应用程序运行完毕退出。和一级缓存一样,如果对相关的资源进行了增删改操作,对应的缓存也会被清除。

发布了60 篇原创文章 · 获赞 7 · 访问量 3870

猜你喜欢

转载自blog.csdn.net/SCUTJAY/article/details/104548441