当前位置: 首页 > news >正文

网站权重排名wordpress首页显示摘要数字

网站权重排名,wordpress首页显示摘要数字,遂宁网站建设公司,婚礼顾问网站介绍模版SqlSession简介Mybatis是一个强大的ORM框架#xff0c;它通过接口式编程为开发者屏蔽了传统JDBC的诸多不便#xff0c;以简单的方式提供强大的扩展能力。其中的接口式编程就是指日常使用的Mapper接口#xff0c;Mybatis借助动态代理实现了sql语句与Mapper的接口的动态绑定它通过接口式编程为开发者屏蔽了传统JDBC的诸多不便以简单的方式提供强大的扩展能力。其中的接口式编程就是指日常使用的Mapper接口Mybatis借助动态代理实现了sql语句与Mapper的接口的动态绑定降低复杂度的同时为开发人员提供强大自主权。经过上一篇文章《Mybatis源码之SQL执行过程》已经知道Mapper其实是Mybatis暴露给开发人员的扩展能力在运行时Mybatis把Mapper接口转为动态方法最终也会转交给SqlSession的CRUD方法执行。所以SqlSession是Mybatis框架真正意义上的命令执行入口。SqlSession是Mybatis中最基础的一个接口类它代表一个与数据库的会话在其生命周期内完成与数据库的交互通过它可以执行基本的SQL命令(select/update/insert/delete)SQL命令具有唯一ID每个ID对应Configration中的一个MappedStatement。获取自定义的Mapper接口对象(getMapper)使用动态代理技术动态生成Mapper接口实现类由MapperProxy代理实现。控制管理事务操作(rollback/commit)数据库事务操作中提交与回滚操作。image.png以上类图为SqlSession等Mybatis接口层的继承体系与关系由上图可知SqlSessionFactory负责SqlSession的创建工作其默认实现为DefaultSqlSessionFactory。SqlSession有两个实现类DefaultSqlSession和SqlSessionManager其中DefaultSqlSession为默认实现SqlSessionManager除了实现SqlSession接口外还实现了SqlSessionFactory接口。接下来我们通过实例和源码来详细了解下DefaultSqlSession和SqlSessionManager两者的特点与差别进一步加深对它的理解。DefaultSqlSessionDefaultSqlSession是SqlSession的默认实现它纯粹是一个功能类完全实现了SqlSession的接口方法但是它并不具备自主管理能力。在开始之前我们先了解两个问题DefaultSqlSession是非线程安全的因此需要避免多线程并发使用随用随取及时释放DefaultSqlSession它不具有自动关闭的能力需要开发者自主调用关闭方法。下面这个示例代码还是跟之前一样我们重点关注第7-9行其实只有两行代码。 1public static void main(String[] args) throws IOException { 2    // mybatis配置文件 3    String path  mybatis-config.xml; 4    InputStream inputStream  Resources.getResourceAsStream(path); 5 6    // 获取 SqlSessionFactory 7    SqlSessionFactory sqlSessionFactory  new SqlSessionFactoryBuilder().build(inputStream); 8    // 创建 SqlSession 9    try (SqlSession sqlSession  sqlSessionFactory.openSession()) {10        // ……11    }12}第7行主要完成配置文件解析并保存到Configuration由SqlSessionFactoryBuilder创建SqlSessionFactory对象为创建SqlSession做准备。第9行采用“try-with-resource”方式调用SqlSessionFactory#openSession方法创建了SqlSession对象。当代码离开try代码块时会自动关闭SqlSession但是这里的自动关闭并不是SqlSession的能力相当于手动调用了SqlSession#close方法。看下openSession的实现 1  public SqlSession openSession() { 2    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); 3  } 4 5  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { 6    Transaction tx  null; 7    try { 8      //获取环境配置信息 9      final Environment environment  configuration.getEnvironment();10      //创建事务处理器11      final TransactionFactory transactionFactory  getTransactionFactoryFromEnvironment(environment);12      tx  transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);13      //创建Executor这里默认使用CachingExecutor14      final Executor executor  configuration.newExecutor(tx, execType);15      //创建SqlSession默认实例DefaultSqlSession16      return new DefaultSqlSession(configuration, executor, autoCommit);17    } catch (Exception e) {18      closeTransaction(tx); // may have fetched a connection so lets call close()19      throw ExceptionFactory.wrapException(Error opening session.  Cause:   e, e);20    } finally {21      ErrorContext.instance().reset();22    }23  }由此可知openSessionFromDataSource方法完成了SqlSession的创建它返回了DefaultSqlSession对象。DefaultSqlSession中聚合了Configuration、Executor等对象。selectXxx方法以selectList为例看下selectXxx方法的执行过程 1  public  List selectList(String statement, Object parameter, RowBounds rowBounds) { 2    try { 3      //statement为MappedStatement的唯一id注册在Configuration#mappedStatements 4      //根据id获取MappedStatement 5      MappedStatement ms  configuration.getMappedStatement(statement); 6      //调用执行器的query方法执行查询命令。 7      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); 8    } catch (Exception e) { 9      throw ExceptionFactory.wrapException(Error querying database.  Cause:   e, e);10    } finally {11      ErrorContext.instance().reset();12    }13  }SqlSession中selectXxx方法最终都走到了selectList方法但是它并没有直接与数据库交互获取MappedStatement对象后调用了执行器Executor的query方法。insert方法insert对应sql的insert命令代码如下 1  public int insert(String statement) { 2    return insert(statement, null); 3  } 4 5  public int insert(String statement, Object parameter) { 6    return update(statement, parameter); 7  } 8 9  public int update(String statement, Object parameter) {10    try {11      dirty  true;12      MappedStatement ms  configuration.getMappedStatement(statement);13      return executor.update(ms, wrapCollection(parameter));14    } catch (Exception e) {15      throw ExceptionFactory.wrapException(Error updating database.  Cause:   e, e);16    } finally {17      ErrorContext.instance().reset();18    }19  }与select类似首先获取MappedStatement然后调用了执行器的update方法。整体流程比较简单有一点需要说明的是对于数据库而言insert/update/delete其实都是更新操作所以这里虽然是insert方法入口但是实际调用了Executor#update方法。delete方法/update方法delete/update方法的执行过程与insert基本是一样的不再赘述。小结DefaultSqlSession是SqlSession的默认实现提供了数据库的CURD能力但是它并没有直接与数据库交互而是调用了Executor的相关方法是一个名副其实的“甩手掌柜”。在selectXxx或insert方法中我们并没有发现它调用close方法所以它不具备自动关闭的能力需要我们开发者手动调用比如示例中的“try-with-resource”方式。回过头来说下“线程安全”通过上述示例和源码我们会发现一旦DefaultSqlSession对象被创建任何获取到它的线程都可以访问其方法CURD或者close多个线程同时操作就会导致不可预知的结果。所以我们不能把它直接设置为公共实例应该即用即取及时释放。SqlSessionManager看完DefaultSqlSession继续看下SqlSessionManager。由上述类图可知它实现了SqlSession和SqlSessionFactory两个接口同时具备SqlSession接口能力及SqlSession对象创建能力。仔细观察类图会发现SqlSessionManager内部还聚合了一个SqlSessionFactory和SqlSession对象什么情况实现了这两个接口却又聚合了这两个接口的实例难道它只是个代理就是包了一层源码走走看 1public class SqlSessionMgrDemo { 2    public static void main(String[] args) throws IOException { 3        // mybatis配置文件 4        String path  mybatis-config.xml; 5        InputStream inputStream  Resources.getResourceAsStream(path); 6        // 获取 SqlSessionManager 7        SqlSessionManager sqlSessionManager  SqlSessionManager.newInstance(inputStream); 8        // 开启对session的管理没有这行代码也可以使用 9        sqlSessionManager.startManagedSession();10        // 获取mapper11        CompanyDao dao  sqlSessionManager.getMapper(CompanyDao.class);12        // 执行查询13        CompanyDO companyDO  dao.selectById(1);14        System.out.println(companyDO);15    }16}简单说下这段代码的执行流程45行加载并读取配置文件7行创建SqlSessionManager实例9行开启对SqlSession的管理通过它可以实现对SqlSession的线程安全管理使SqlSessionManager实例可共享(这个与DefaultSqlSession有差别)1114行执行查询实例化通过示例代码可知SqlSessionManager#newInstance创建了SqlSessionManager对象看下执行过程我们仔细看看SqlSessionManager到底是个什么东东。 1// 创建 SqlSessionManager 2public static SqlSessionManager newInstance(InputStream inputStream) { 3  return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, null)); 4} 5 6// 构造方法这里入参为DefaultSqlSessionFactory实例 7private SqlSessionManager(SqlSessionFactory sqlSessionFactory) { 8 9  this.sqlSessionFactory  sqlSessionFactory;1011  // 通过动态代理创建SqlSession实例12  this.sqlSessionProxy  (SqlSession) Proxy.newProxyInstance(13      SqlSessionFactory.class.getClassLoader(),14      new Class[]{SqlSession.class},15      new SqlSessionInterceptor());16}1718// SqlSessionFactory实例19private final SqlSessionFactory sqlSessionFactory;2021// SqlSession 代理对象22private final SqlSession sqlSessionProxy;newInstance方法调用了SqlSessionManager的私有构造方法(仅有私有构造方法)构造方法的入参是SqlSessionFactory(与DefaultSqlSession的实现一致)这里是其默认实现DefaultSqlSessionFactory。构造方法内通过动态代理创建对象sqlSessionProxy它是SqlSession的动态实现这里需要重点关注SqlSessionInterceptor这个类。从名称看它是一个拦截器也就是说当我们调用SqlSession的方法时会被它拦截看下SqlSessionInterceptor#invoke方法 1  private class SqlSessionInterceptor implements InvocationHandler { 2    public SqlSessionInterceptor() { 3        // Prevent Synthetic Access 4    } 5 6    Override 7    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 8 9      // 判断本地线程是否有sqlSession10      final SqlSession sqlSession  SqlSessionManager.this.localSqlSession.get();11      // 如果有直接使用无需创建12      if (sqlSession ! null) {13        try {14          // 调用SqlSession接口方法实现15          return method.invoke(sqlSession, args);16        } catch (Throwable t) {17          throw ExceptionUtil.unwrapThrowable(t);18        }19      } else {20        // 如果没有通过openSession创建openSession方法返回的是DefaultSqlSession实例21        //这里使用try-with-resource使用完成会自动关闭22        try (SqlSession autoSqlSession  openSession()) {23          try {24            // 调用SqlSession接口方法实现25            final Object result  method.invoke(autoSqlSession, args);26            //事务提交27            autoSqlSession.commit();28            return result;29          } catch (Throwable t) {30            //事务回滚31            autoSqlSession.rollback();32            throw ExceptionUtil.unwrapThrowable(t);33          }34        }35      }36    }37  }SqlSessionInterceptor#invoke首先会从localSqlSession获取SqlSession对象localSqlSession是什么呢这里只提到get那set在哪里从代码里面找下吧 1  //localSqlSession是一个ThreadLocal对象用来存储SqlSession 2  //这是一个线程安全的标志 3  private final ThreadLocal localSqlSession  new ThreadLocal(); 4 5  //开启对SqlSession的管理我们示例代码有调用 6  public void startManagedSession() { 7    //为localSqlSession赋值参数为openSession返回值 8    this.localSqlSession.set(openSession()); 9  }1011  public SqlSession openSession() {12    //与之前一样它返回的是DefaultSqlSession对象13    return sqlSessionFactory.openSession();14  }localSqlSession是一个ThreadLocal对象用来存储SqlSession它用来在线程内共享对象很明显的线程安全处理方式。localSqlSession是在startManagedSession及其重载方法中设置的通过openSession方法可知localSqlSession内部存放的是DefaultSqlSession对象。继续SqlSessionInterceptor#invoke分析根据localSqlSession中是否存有sqlSession有两个不同的处理方式有如果有则直接使用不再新建。这里只能是在同一线程内共享避免了重复创建对象的额外开销。无如果没有就与我们DefaultSqlSession一节中的使用方式一样使用了“try-with-resource”方式实现了SqlSession的自动关闭。SqlSessionManager持有的SqlSessionFactory引用为DefaultSqlSessionFactory作用自然是创建SqlSession实例SqlSessionFactory创建的SqlSession是DefaultSqlSession实例但是SqlSessionManager内部通过动态代理模式使用SqlSessionInterceptor对DefaultSqlSession进行了拦截在拦截处理中有两种逻辑一是使用ThreadLocal对SqlSession进行了线程安全共享二是实现了对SqlSession的自动关闭。由此可见SqlSessionManager是DefaultSqlSession的加强版或者说是一个高级封装。SqlSession接口实现SqlSessionManager对SqlSession接口的实现全部转交给其内部的sqlSessionProxy代理对象完成没有什么处理逻辑贴几个方法看下 1  public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { 2    sqlSessionProxy.select(statement, parameter, rowBounds, handler); 3  } 4 5  public int insert(String statement) { 6    return sqlSessionProxy.insert(statement); 7  } 8 9  public int update(String statement) {10    return sqlSessionProxy.update(statement);11  }1213  public int delete(String statement) {14    return sqlSessionProxy.delete(statement);15  }sqlSessionProxy其实是一个包装了DefaultSqlSession的SqlSessionInterceptor实例所有方法会被SqlSessionInterceptor#invoke拦截最终是由DefaultSqlSession来实现的(就是前面一节说的内容)。前面“实例化”一节说invoke内有两种逻辑那实际会走哪种逻辑呢实际上这引出了SqlSessionManager的两种使用方式使用方式不同invoke的执行逻辑也不同。一是像使用DefaultSqlSession一样按需创建此时SqlSessionManager提供了自动关闭功能。二是启用SqlSession管理功能。此时SqlSessionManager会在同一线程内共享SqlSession它是线程安全的。小伙伴儿们可以尝试把示例代码中第9行关闭或打开注释作下调试一试便知。小结SqlSessionManager虽然同时实现了SqlSession和SqlSessionFactory两个接口但是真正“干活”的还是DefaultSqlSession和DefaultSqlSessionFactory它使用动态代理对SqlSession的方法进行拦截提供了SqlSession自动关闭或线程安全的解决方案。整体上看SqlSessionManager是对安全、智能、高级封装版的DefaultSqlSession。SqlSession总结本文“啰里八嗦”的介绍了DefaultSqlSession和SqlSessionManager两者的区别与联系重点关注了SqlSessionManager如何解决线程安全和自动关闭两个问题从源码层面了解到SqlSessionManager其实是对DefaultSqlSession的高级封装。我们还了解到所有的SQL命令都会从SqlSession开始然而SqlSession并没有直接操作数据库脏活累活都交给了Executor形象点说SqlSession其实是一个“包工头儿”。具体Executor如何做且听下文讲解。感谢您的阅读如有问题欢迎讨论也可以关注我的微信公众号“兮一昂吧”。欢迎点赞、在看、转发。
http://www.zqtcl.cn/news/93546/

相关文章:

  • 北京管庄网站建设公司开平网站制作
  • 如何做销售直播网站最专业网站建设
  • 太原市住房和城乡建设局的网站首页网络推广服务外包公司
  • 湘icp备 网站建设 农业 湖南稿定设计免费版
  • 公司网站推广方法陕西省住房建设厅官网
  • 网站关键词排名突然没了无锡企业网站建设报价
  • 找做网站的人网站改版 301跳转
  • 网站备案一次就可以了吧营销管理培训课程
  • 怎么做网站背景专做民宿预定的网站
  • wordpress安装谷歌分析代码建网站seo
  • 百度外卖网站建设与维护方法建设 银行网网站
  • 小程序开发定制开发上海优化价格
  • 来宾住房和城乡建设局网站做外贸推广要做哪些平台
  • 无锡建设网站制作wordpress 知乎
  • 动漫网站源码免费怎么怎么做网站
  • 和两个黑人同时做网站中工互联网站建设
  • windows10PHP 网站建设app应用分发平台开发
  • 中唯建设工程有限公司网站做网站页面对PS切图
  • 个人网页制作成品欣赏seo网站沙盒期
  • 亚马逊站外推广网站怎么做制作营销网站模板免费下载
  • 加拿大网站后缀设计师互联网
  • 做物流的网站有哪些内容共同建设网站心得
  • 主题资源网站建设什么网站做污水处理药剂的好
  • 河北建设厅网站修改密码在哪58同城宿迁二手房
  • 淘宝联盟的购物网站怎么做免费网站模板素材
  • 淄博市网站云平台长沙seo 优化选智投未来no1
  • 手机网站导航模板wordpress子域名设置
  • 济南市网站推广公司甘肃网站建设方案优化
  • 网站排名西安工商所什么网站可做年报
  • 网站怎样做反向链接哪个网站可以做代码题目