12.mybatis核心架构原理

Mybatis环境搭建

Mybatis介绍

https://mybatis.net.cn/index.html

mybatis是一个用Java编写的持久层框架,它使用ORM实现了结果集的封装。

ORM是Object Relational Mapping 对象关系映射。简单来说,就是把数据库表和实体类及实体类的属性对应起来,让开发者操作实体类就实现操作数据库表,它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等复杂过程。

ORM:Object-Relation-Mapping,也就是对象关系映射,是一种程序设计思想,mybatis就是ORM的一种实现方式,简单来说就是将数据库中查询出的数据映射到对应的实体中。

数据库表结构

 CREATE TABLE `mayikt_users` (   `id` int NOT NULL AUTO_INCREMENT,   `name` varchar(255) DEFAULT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;

1.引入mybatis相关依赖 已经完成了

2.mybatis-config.xml(该配置文件名称是可以改) 存放就是我们数据库相关连接信息

3.定义mapper ----编写我们mybatis 相关 sql语句 每个表 对应一个mapper

4.定义java对象--需要注意下 类中的 成员属性与数据库表中字段 映射 默认 类中的 成员属性数据库表中字段名称对应的。

5.使用 mybatis api开始执行该 sql语句即可 得到结果

maven依赖

                      org.mybatis             mybatis             3.4.5                               mysql             mysql-connector-java             8.0.18         


定义xml配置文件

存放数据库连接信息mybatis-config.xml

 <?xml version="1.0" encoding="UTF-8" ?>                                                                                                                                                             

Mapper文件

 <?xml version="1.0" encoding="UTF-8" ?>        

测试代码

 package com.mayikt.test;  import com.mayikt.entity.UserEntity; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder;  import java.io.IOException; import java.io.InputStream; import java.util.List;  /** * @author songchuanfu * @qq 1802284273 */ public class Test01 {     public static void main(String[] args) throws IOException {         // 1.读取加载mybatis-config.xml         String resource = "mybatis-config.xml";         InputStream inputStream = Resources.getResourceAsStream(resource);         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);         // 2.获取到获取到         SqlSession sqlSession = sqlSessionFactory.openSession();         // 3.根据 mapper id=getByUsers 执行该s  ql 语句 通过  sql语句得到我们的对象 orm         List userEntitys = sqlSession.selectList("getByUsers", UserEntity.class);         System.out.println(userEntitys);         sqlSession.close();     } }

mapper代理开发模式

1.mapper接口方式开发整合就必须是对应的mapper接口的全限定类名

2.接口中的方法与映射文件中的SQL语句的ID

3.需要在mybatis-config.xml 新增 加载该userMaaper

4.定义mapper 接口 需要考虑方法的名称与userMapper.xml的 sql id名称保持一致。

 package com.mayikt.mapper;  import com.mayikt.entity.UserEntity;  import java.util.List;  /** * @author songchuanfu * @qq 1802284273 */ public interface UserMapper {     List getByUsers(); }  <?xml version="1.0" encoding="UTF-8" ?>        

5.相关代码

 package com.mayikt.test;  import com.mayikt.entity.UserEntity; import com.mayikt.mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder;  import java.io.IOException; import java.io.InputStream; import java.util.List;  /** * @author songchuanfu * @qq 1802284273 */ public class Test01 {     public static void main(String[] args) throws IOException {         // 1.读取加载mybatis-config.xml         String resource = "mybatis-config.xml";         InputStream inputStream = Resources.getResourceAsStream(resource);         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);         // 2.获取到获取到         SqlSession sqlSession = sqlSessionFactory.openSession();         // 3.根据 mapper id=getByUsers 执行该s  ql 语句 通过  sql语句得到我们的对象 orm //        List userEntitys = sqlSession.selectList("getByUsers", UserEntity.class);         UserMapper mapper = sqlSession.getMapper(UserMapper.class);         System.out.println(mapper.getByUsers()); //        System.out.println(userEntitys);         sqlSession.close();     } }

mybatis使用设计模式

1、Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;(解析配置文件)

2、工厂模式,例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;

3、单例模式,例如ErrorContext和LogFactory;

4、代理模式,Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果;调动我们的Mapper接口

5、组合模式,例如SqlNode和各个子类ChooseSqlNode等;

6、模板方法模式,例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;

7、适配器模式,例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;

8、装饰者模式,例如Cache包中的cache.decorators子包中等各个装饰者的实现;(多级缓存)

9、迭代器模式,例如迭代器模式PropertyTokenizer;

简单手写mybatis大致原理

底层基于jdk动态代理实现

mybatis mapper接口分析

在mybatis mapper 是一个接口为何可以调用的呢?底层其实就是基于JDK动态代理实现。

相关代码:

 package com.mayikt.mybatis.ext;  import org.springframework.stereotype.Indexed;  import java.lang.annotation.*;  /** * @author songchuanfu * @qq 1802284273 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Indexed public @interface MayiktInsert {     String value(); }  package com.mayikt.mybatis;  import com.mayikt.mybatis.ext.MayiktInsert; import com.mayikt.utils.MayiktJdbcUtils; import org.apache.commons.lang.StringUtils;  import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.PreparedStatement;  /** * @author songchuanfu * @qq 1802284273 */ public class MybatisJdkInvocationHandler implements InvocationHandler {     private Class mapperClass;      public MybatisJdkInvocationHandler(Class mapperClass) {         this.mapperClass = mapperClass;     }      @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         // 使用java反射技术获取该方法上的注解         MayiktInsert declaredAnnotation = method.getDeclaredAnnotation(MayiktInsert.class);         String insertSql = declaredAnnotation.value();         if (StringUtils.isEmpty(insertSql)) {             return null;         }         // 执行该sql语句         Connection connection = MayiktJdbcUtils.getConnection();         PreparedStatement preparedStatement = connection.prepareStatement(insertSql);         int result = preparedStatement.executeUpdate();         return result;     }      public  T getProxy() {         return (T) Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, this);     } }  package com.mayikt.mybatis;  import com.mayikt.mybatis.ext.MayiktInsert;  /** * @author songchuanfu * @qq 1802284273 */ public interface UserMapper {     @MayiktInsert("INSERT INTO `mayikt`.`mayikt_users` (`id`, `name`, `age`) VALUES (null, 'wangmazi', NULL);")     int addUser(); }  package com.mayikt.mybatis;  /** * @author songchuanfu * @qq 1802284273 */ public class Test01 {     public static void main(String[] args) {         System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");         UserMapper userMapper = MapperProxy.getUserMapper(UserMapper.class);         int result = userMapper.addUser();         System.out.println(result);     } }  package com.mayikt.mybatis;  /** * @author songchuanfu * @qq 1802284273 */ public class MapperProxy {     public static UserMapper getUserMapper(Class mapperClass) {         return new MybatisInvocationHandler(mapperClass).getProxy();     }      public static void main(String[] args) {         // 将jdk动态生成好的 class 存放本地         System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");         UserMapper userMapper = MapperProxy.getUserMapper(UserMapper.class);         int i = userMapper.addUser();         System.out.println(i);     } }

mybatis 底层 mapper 接口会执行到MapperProxy

会执行到:MapperProxy

mybatis mapperjdk动态代理源码解读

jdk动态代理 底层 生成 mapper 代理类

public final class $Proxy4 extends Proxy implements UserMapper {

}

当我们在去调用$Proxy4.方法的时候 会执行 mybatis jdk 动态代理回调类

 public class MapperProxy implements InvocationHandler, Serializable {          private static final long serialVersionUID = -6424540398559729838L;     private final SqlSession sqlSession;     private final Class mapperInterface;     private final Map methodCache;          public MapperProxy(SqlSession sqlSession, Class mapperInterface, Map methodCache) {         this.sqlSession = sqlSession;         this.mapperInterface = mapperInterface;         this.methodCache = methodCache;     }          @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         try {             if (Object.class.equals(method.getDeclaringClass())) {                 return method.invoke(this, args);             } else if (isDefaultMethod(method)) {                 return invokeDefaultMethod(proxy, method, args);             }         } catch (Throwable t) {             throw ExceptionUtil.unwrapThrowable(t);         }         // 执行到我们 mapperMethod.execute(sqlSession, args);         final MapperMethod mapperMethod = cachedMapperMethod(method);         return mapperMethod.execute(sqlSession, args);     }          private MapperMethod cachedMapperMethod(Method method) {         MapperMethod mapperMethod = methodCache.get(method);         if (mapperMethod == null) {             mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());             methodCache.put(method, mapperMethod);         }         return mapperMethod;   }          return mapperMethod.execute(sqlSession, args);     判断sql语句类型 select、insert、delete、update             public Object execute(SqlSession sqlSession, Object[] args) {     Object result;     switch (command.getType()) {       case INSERT: {         Object param = method.convertArgsToSqlCommandParam(args);         result = rowCountResult(sqlSession.insert(command.getName(), param));         break;       }       case UPDATE: {         Object param = method.convertArgsToSqlCommandParam(args);         result = rowCountResult(sqlSession.update(command.getName(), param));         break;       }       case DELETE: {         Object param = method.convertArgsToSqlCommandParam(args);         result = rowCountResult(sqlSession.delete(command.getName(), param));         break;       }       case SELECT:         if (method.returnsVoid() && method.hasResultHandler()) {           executeWithResultHandler(sqlSession, args);           result = null;         } else if (method.returnsMany()) {           result = executeForMany(sqlSession, args);         } else if (method.returnsMap()) {           result = executeForMap(sqlSession, args);         } else if (method.returnsCursor()) {           result = executeForCursor(sqlSession, args);         } else {           Object param = method.convertArgsToSqlCommandParam(args);           result = sqlSession.selectOne(command.getName(), param);         }         break;       case FLUSH:         result = sqlSession.flushStatements();         break;       default:         throw new BindingException("Unknown execution method for: " + command.getName());     }     if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {       throw new BindingException("Mapper method '" + command.getName()            + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");     }     return result;   }        name:Mapper类完整路径地址+方法名称组合   通过源码分析可以得出 底层 result = sqlSession.selectList(command.getName(), param);     

mybatis运行的原理

1.初始化阶段:读取 解析XML 配置文件和注解中的配置信息,创建配置对象,并完成各个模块的初始化的工作,底层采用建造模式

2.代理封装阶段:封装 mybatis 的编程模型,使用 mapper 接口开发的初始化工作,底层爱用jdk动态代理模式

3.数据访问阶段:通过 SqlSession 完成 SQL 的解析,参数的映射、SQL 的执行、结果的解析过程;

谈谈建造模式模式设计原理

什么是建造者模式

建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

以下情况建议使用建造者模式:

1、某个对象有复杂的内部结构,通常包含多个成员属性,而且属性是可选的。

2、相同的方法,不同的执行顺序,产生不同的对象或不同的运行结果。

3、当创建一个对象需要很多步骤时,适合使用建造者模式。

建造者模式应用场景

1.mybatis 解析xml

2.StringBuilder

3.OkHttpClient

Request request = new Request.Builder().url("http://www.mayikt.com").build();.build();)

建造者模式小案例

例如我们现在封装HttpClient框架,里面有很多配置属性

例如 接口url、请求方法、超时时间、body等

 方式1:  new MayiktHttpClient("http://www.mayikt.com", "POST"); new MayiktHttpClient("http://www.mayikt.com", "POST", 10000l); 方式2:  MayiktHttpClient post = new MayiktBuilder().setUrl("http://www.mayikt.com")                 .setMethod("POST").setBody("mayikt").setTimeout(1000l).build(); System.out.println(post); package com.mayikt.test;  /** * @author songchuanfu * @qq 1802284273 */ public class MayiktHttpClient {     /**      * 请求url      */     private String url;     /**      * 请求方法      */     private String method;      /**      * 超时时间      */     private Long timeout;     /**      * 内容      */     private String body;      public MayiktHttpClient(String url, String method) {         this.url = url;         this.method = method;     }      public MayiktHttpClient() {      }     //retry       public String getUrl() {         return url;     }      public void setUrl(String url) {         this.url = url;     }      public String getMethod() {         return method;     }      public void setMethod(String method) {         this.method = method;     }      public Long getTimeout() {         return timeout;     }      public void setTimeout(Long timeout) {         this.timeout = timeout;     }      public String getBody() {         return body;     }      public void setBody(String body) {         this.body = body;     } }

我们使用

 new MayiktHttpClient("http://www.mayikt.com", "POST")

如果需要传递三个参数 看起来逼格不是很高

 new MayiktHttpClient("http://www.mayikt.com", "POST",10000l);
 package com.mayikt.test;  /** * @author songchuanfu * @qq 1802284273 */ public class MayiktBuilder {     /**      * 请求url      */     private String url;     /**      * 请求方法      */     private String method;      /**      * 超时时间      */     private Long timeout;     /**      * 内容      */     private String body;      public MayiktHttpClient build() {         return new MayiktHttpClient(this);     }      public MayiktBuilder setUrl(String url) {         this.url = url;         return this;     }      public MayiktBuilder setMethod(String method) {         this.method = method;         return this;     }      public MayiktBuilder setTimeout(Long timeout) {         this.timeout = timeout;         return this;     }      public MayiktBuilder setBody(String body) {         this.body = body;         return this;     }      public String getMethod() {         return method;     }       public String getUrl() {         return url;     }      public Long getTimeout() {         return timeout;     }       public String getBody() {         return body;     }  }  package com.mayikt.test;  /**  * @author 余胜军  * @ClassName MayiktHttpClient  * @qq 644064779  * @addres www.mayikt.com  * 微信:yushengjun644  */ public class MayiktHttpClient {     /**      * 请求url      */     private String url;     /**      * 请求方法      */     private String method;      /**      * 超时时间      */     private Long timeout;     /**      * 内容      */     private String body;      public MayiktHttpClient(String url, String method) {         this.url = url;         this.method = method;     }      public MayiktHttpClient(String url, String method, Long timeout) {         this.url = url;         this.method = method;         this.timeout = timeout;     }      public MayiktHttpClient(MayiktBuilder mayiktBuilder) {         this.url = mayiktBuilder.getUrl();         this.body = mayiktBuilder.getBody();         this.method = mayiktBuilder.getMethod();         this.timeout = mayiktBuilder.getTimeout();     }      public MayiktHttpClient() {      }     //retry       public String getUrl() {         return url;     }      public void setUrl(String url) {         this.url = url;     }      public String getMethod() {         return method;     }      public void setMethod(String method) {         this.method = method;     }      public Long getTimeout() {         return timeout;     }      public void setTimeout(Long timeout) {         this.timeout = timeout;     }      public String getBody() {         return body;     }      public void setBody(String body) {         this.body = body;     }      @Override     public String toString() {         return "MayiktHttpClient{" +                 "url='" + url + '\'' +                 ", method='" + method + '\'' +                 ", timeout=" + timeout +                 ", body='" + body + '\'' +                 '}';     } }

用法:

 new MayiktHttpClient("http://www.mayikt.com", "POST"); new MayiktHttpClient("http://www.mayikt.com", "POST", 10000l); MayiktHttpClient post = new MayiktBuilder().setUrl("http://www.mayikt.com")     .setMethod("POST").setBody("mayikt").setTimeout(1000l).build(); System.out.println(post);

相关代码

mybatis源码解读01.rar

mybatis 建造模式源码解读

configuration

configuration 对象的关键属性解析如下:

MapperRegistry:mapper 接口动态代理工厂类的注册中心。在 MyBatis 中,通过mapperProxy 实现 InvocationHandler 接口,MapperProxyFactory 用于生成动态代理的实例对象;

ResultMap:用于解析 mapper.xml 文件中的 resultMap 节点,使用 ResultMapping 来封装id,result 等子元素;

MappedStatement:用于存储 mapper.xml 文件中的 select、insert、update 和 delete 节点,同时还包含了这些节点的很多重要属性;

SqlSource:用于创建 BoundSql,mapper.xml 文件中的 sql 语句会被解析成 BoundSql 对象,经过解析 BoundSql 包含的语句最终仅仅包含?占位符,可以直接提交给数据库执行;

mybatis解析xml配置文件源码解读

 SqlSessionFactory sqlSessionFactory =      new SqlSessionFactoryBuilder().build(inputStream);

1.BaseBuilder:所有解析器的父类,包含配置文件实例,为解析文件提供的一些通用的方法;

2.XMLConfigBuilder: 主要负责解析 mybatis-config.xml;

3.XMLMapperBuilder: 主要负责解析映射配置 Mapper.xml 文件;

4.XMLStatementBuilder: 主要负责解析映射配置文件中的 SQL 节点;

mybatis-config.xml读取配置源码解读

1.mybatis 底层采用 dom解析配置xml配置

 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {     try {     //读取xml相关配置       XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);           public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {     this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);   }             private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {     super(new Configuration());     ErrorContext.instance().resource("SQL Mapper Configuration");     this.configuration.setVariables(props);       //标记 如果parsed该是为false没有解析 如果是为true的情况下       //则是已经解析过 parsed=true     this.parsed = false;     this.environment = environment;     this.parser = parser;   }    public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {     commonConstructor(validation, variables, entityResolver);      //读取xml相关配置(dom)     this.document = createDocument(new InputSource(inputStream));   }     private Document createDocument(InputSource inputSource) {     // important: this must only be called AFTER common constructor     try {       DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();       factory.setValidating(validation);        factory.setNamespaceAware(false);       factory.setIgnoringComments(true);       factory.setIgnoringElementContentWhitespace(false);       factory.setCoalescing(false);       factory.setExpandEntityReferences(true);        DocumentBuilder builder = factory.newDocumentBuilder();       builder.setEntityResolver(entityResolver);       builder.setErrorHandler(new ErrorHandler() {         @Override         public void error(SAXParseException exception) throws SAXException {           throw exception;         }          @Override         public void fatalError(SAXParseException exception) throws SAXException {           throw exception;         }          @Override         public void warning(SAXParseException exception) throws SAXException {         }       });       // 解析xml配置       return builder.parse(inputSource);     } catch (Exception e) {       throw new BuilderException("Error creating document instance.  Cause: " + e, e);     }   }

断点debug 查看document 解析xml配置成功

mybatis解析mapper相关配置

 在new new XMLConfigBuilder(inputStream, environment, properties); 中   private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {     super(new Configuration());     ErrorContext.instance().resource("SQL Mapper Configuration");     this.configuration.setVariables(props);     this.parsed = false;  //已经解析是为false     this.environment = environment;     this.parser = parser;   }           public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {     try {       XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);       //读取xml成功之后开始解析xml              return build(parser.parse());     //解析xml成功之后会得到一个 Configuration    public Configuration parse() {      //因为在构造函数设置了parsed 为fasle,每个XMLConfigBuilder只能使用一次。     if (parsed) {       throw new BuilderException("Each XMLConfigBuilder can only be used once.");     }     // 标识为:true     parsed = true;     //开始从根节点解析           parseConfiguration(parser.evalNode("/configuration"));     return configuration;   } !-- 数据库相关的配置-->                                                           mapperInterface = Resources.classForName(mapperClass);             configuration.addMapper(mapperInterface);           } else {             throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");           }         }       }     }   }                  

解析我们的resource相关配置

   public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {     commonConstructor(validation, variables, entityResolver);     this.document = createDocument(new InputSource(inputStream));   }   private Document createDocument(InputSource inputSource) {     // important: this must only be called AFTER common constructor     try {       DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();       factory.setValidating(validation);        factory.setNamespaceAware(false);       factory.setIgnoringComments(true);       factory.setIgnoringElementContentWhitespace(false);       factory.setCoalescing(false);       factory.setExpandEntityReferences(true);        DocumentBuilder builder = factory.newDocumentBuilder();       builder.setEntityResolver(entityResolver);       builder.setErrorHandler(new ErrorHandler() {         @Override         public void error(SAXParseException exception) throws SAXException {           throw exception;         }          @Override         public void fatalError(SAXParseException exception) throws SAXException {           throw exception;         }          @Override         public void warning(SAXParseException exception) throws SAXException {         }       });       return builder.parse(inputSource);     } catch (Exception e) {       throw new BuilderException("Error creating document instance.  Cause: " + e, e);     }   }

解析完成配置文件之后:将我们的Configuration交给DefaultSqlSessionFactory

openSession源码解读

 @Override public SqlSession openSession() {     // 默认传递一个执行 ----简单的执行器     return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);   }   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {     Transaction tx = null;     try {       // 获取环境配置       final Environment environment = configuration.getEnvironment();       // 获取TransactionFactory       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);       // 获取Transaction事务       tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);       // 根据事务 execType 获取 Executor 执行器       final Executor executor = configuration.newExecutor(tx, execType);       // new DefaultSqlSession 最后封装我们的configuration、executor、autoCommit       // 封装到DefaultSqlSession返回。                return new new DefaultSqlSession(configuration, executor, autoCommit);     } catch (Exception e) {       closeTransaction(tx); // may have fetched a connection so lets call close()       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);     } finally {       ErrorContext.instance().reset();     }   } //获取 Executor 执行器   public Executor newExecutor(Transaction transaction, ExecutorType executorType) {     executorType = executorType == null ? defaultExecutorType : executorType;     executorType = executorType == null ? ExecutorType.SIMPLE : executorType;     Executor executor;     if (ExecutorType.BATCH == executorType) {       executor = new BatchExecutor(this, transaction);     } else if (ExecutorType.REUSE == executorType) {       executor = new ReuseExecutor(this, transaction);     } else {       executor = new SimpleExecutor(this, transaction);     }     // 如果cacheEnabled是为true 返回CachingExecutor 判断是否开启了二级缓存     // 走我们的CachingExecutor 执行器     if (cacheEnabled) {       executor = new CachingExecutor(executor);     }     executor = (Executor) interceptorChain.pluginAll(executor);     return executor;   }

SimpleExecutor:默认的Executor,每个SQL执行时候都会创建新的Statement

ReuseExecutor:相同的SQL会重复使用Statement

BatchExecutor:用于批处理的Executor

CachingExecutor:可缓存数据的Executor,用代理模式包装了其他类型的Executor

// 如果cacheEnabled是为true 返回CachingExecutor 则开启mybatis 二级缓存

 <?xml version="1.0" encoding="UTF-8" ?>                                                                                                                                                                                                            

*//3. 创建SqlSessionFactoryBuilder.build(inputStream) 建造者 键盘快捷键ctrl+点击方法 *SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); *//4.获取到session //传递true 或者false 是否自动提交 true *SqlSession sqlSession = sqlSessionFactory.openSession(false);

1.解析mybatis-configxml 得到Configuration 在将该对象赋值给我们SqlSessionFactory

new SqlSessionFactoryBuilder().build(inputStream);

2.使用sqlSessionFactory 得到SqlSession 对象时 判断当前使用的执行器类型

SimpleExecutor:默认的Executor,每个SQL执行时候都会创建新的Statement

ReuseExecutor:相同的SQL会重复使用Statement

BatchExecutor:用于批处理的Executor

CachingExecutor:可缓存数据的Executor,用代理模式包装了其他类型的Executor

// 如果cacheEnabled是为true 返回CachingExecutor 则开启mybatis 二级缓存

默认采用SimpleExecutor 执行器 如果开启了二级缓存则使用CachingExecutor

SqlSession sqlSession = sqlSessionFactory.openSession(false);

最后返回了我们的默认的SqlSession

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章