# My-ORM
**Repository Path**: JINO8/My-ORM
## Basic Information
- **Project Name**: My-ORM
- **Description**: 自定义ORM框架
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2019-12-29
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
一、简单题
1、Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理?
答:a、mybatis通过逻辑判断和解析XML中的sql标签,来动态拼接sql,然后执行拼接好的sql,和数据库交互;
b、9个SQL标签:、、、、、、、、;
c、执行原理为,使用OGNL的表达式,从SQL参数对象中计算表达式的值,根据表达式的值动态拼接SQL,以此来完成动态SQL的功能。
2、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
答:a、Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,
collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
b、原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),
拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),
于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
3、Mybatis都有哪些Executor执行器?它们之间的区别是什么?
答:a、Mybatis-3.5.3中总共有5种Executor执行器:BatchExecutor、CachingExecutor、ClosedExecutor、ReuseExecutor、SimpleExecutor;
b、BatchExecutor:支持批处理的执行器,执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中addBatch(),
等待统一执行executeBatch(),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,
等待逐一执行executeBatch()批处理。与JDBC批处理相同。
CachingExecutor:自带事务管理的缓存执行器,可以很灵活的支持一级缓存和二级缓存。
ClosedExecutor:关闭的执行器,这是在ResultLoaderMap中继承的一个final的静态内部类(不推荐使用)。
ReuseExecutor:重复利用Statement对象的执行器,执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,
用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
SimpleExecutor:简单执行器(默认使用),每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
4、简述下Mybatis的一级、二级缓存(分别从存储结构、范围、失效场景。三个方面来作答)?
答:存储结构:Mybatis的一级、二级缓存底层存储结构都是map;
范围:一级缓存是sqlSession级别的,二级缓存是基于namespace设计的夸session的缓存;
失效场景:a、分布式环境下,二级缓存会失效,因为二级缓存默认是基于本地存储的,可以借助第三方存储,如redis来解决;
b、Mybatis与Spring进行整合时,一级缓存会失效,mybatis会在每次查询之后自动关闭sqlSession,可以加上@Transactional注解来解决;
5、简述Mybatis的插件运行原理,以及如何编写一个插件?
答:Mybatis底层创建Executor/ParameterHandler/ResultSetHander/StatementHandler这4大对象时,都会调用interceptorChain的pluginAll方法,
这个pluginAll方法就是遍历所有的拦截器,然后顺序执行我们插件的plugin方法,一层一层返回我们原对象(Executor/ParameterHandler/ResultSetHander
/StatementHandler)的代理对象。当我们调用四大接口对象的方法时候,实际上是调用代理对象的响应方法,代理对象又会调用四大接口对象的实例;
通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。
如下:(伪代码)
// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
private Properties properties = new Properties();
public Object intercept(Invocation invocation) throws Throwable {
// 执行方法之前。。
Object returnObject = invocation.proceed();
// 执行方法之后。。
return returnObject;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
二、编程题
请完善自定义持久层框架IPersistence,在现有代码基础上添加、修改及删除功能。
(已完成,详见代码My-ORM中的IPersistence模块)