浅谈Mybatis连接原理

       众所周知数据库连接的过程,但是最近面试的人(菜面菜),都说用的SSM框架,但是我问了一下,mybatis是怎么连接上mysql的,基本上都会说:配置好的,直接用了,今天我来抛砖引玉一下,欢迎拍砖!

       什么是JDBC?

       Java语言访问数据库的一种规范,是一套API。JDBC (Java Database Connectivity) API,即Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库。JDBC规范采用接口和实现分离的思想设计了Java数据库编程的框架。接口包含在java.sql及javax.sql包中,其中java.sql属于JavaSE,javax.sql属于JavaEE。为了使客户端程序独立于特定的数据库驱动程序,JDBC规范建议开发者使用基于接口的编程方式,即尽量使应用仅依赖java.sql及javax.sql中的接口和类。

        JAVA使用JDBC访问数据库的步骤:

        1.得到数据库驱动程序

        2.创建数据库连接

        3.执行SQL语句

        4.得到结果集

        5.对结果集做相应的处理(增,删,改,查)

        6.关闭资源:这里释放的是DB中的资源

        mysql的驱动包提供了java.sql.Driver这个SPI的实现,实现类是com.mysql.jdbc.Driver,在mysql-connector-java-5.1.6.jar中,我们可以看到有一个META-INF/services目录,目录下有一个文件名为java.sql.Driver的文件,其中的内容是com.mysql.jdbc.Driver。
在运行DriverManager.getDriver并传入参数“com.mysql.jdbc.Driver”时,DriverManager会从mysql-connector-java-5.1.6.jar中找到com.mysql.jdbc.Driver并实例化返回一个com.mysql.jdbc.Driver的实例。而SPI(Service Provider Interface)是指一些提供给你继承、扩展,完成自定义功能的类、接口或者方法。

       SPI是一种回调的思想,回调是指我们在使用api时,我们可以向API传入一个类或者方法,API在合适的时间调用类或者方法。SPI是在一些通用的标准中,为标准的实现产商提供的扩展点。标准在上层提供API,API内部使用了SPI,当API被客户使用时,会动态得从当前运行的classpath中寻找该SPI的实现,然后使用该SPI的实现来完成API的功能。
       SPI的实现方式是:提供实现的实现类打包成Jar文件,这个Jar文件里面必须有META-INF目录,其下又有services目录,其下有一个文本文件,文件名即为SPI接口的全名,文件的内容该jar包中提供的SPI接口的实现类名。
       大家看项目中Mybaits的jar包会发现:
private class SqlSessionInterceptor implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);
      try {
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
          // release the connection to avoid a deadlock if the translator is no loaded. See issue #22
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
          sqlSession = null;
          Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
          if (translated != null) {
            unwrapped = translated;
          }
        }
        throw unwrapped;
      } finally {
        if (sqlSession != null) {
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }
      }
    }
  }

      sqlSessionTemplate.SqlSessionInterceptor源码,有没有一种很熟悉的感觉?至于getConnection自己去看;用过ElasticSearch和Redis的童鞋,细心的童鞋会发现连接字符串都大同小异,连接都是类似的,标准的连接方式,提高效率,有效控制连接;

      ElasticSearch的连接字符串:

protected SearchResponse getSearchResponse(String fieldName, String indexName) {
    client = null;
    SearchResponse response = null;
    try {
        getClient();
        MaxAggregationBuilder aggregation =
                AggregationBuilders
                        .max("agg")
                        .field(fieldName);
        SearchRequestBuilder request = client.prepareSearch(indexName).addAggregation(aggregation);
        response = request.execute().actionGet();
    } catch (Exception ex) {
        logger.error("getSearchResponse", ex);
    } finally {
        if (client != null) {
            client.close();
        }
        return response;
    }
}

     Jedis连接字符串:

执行命令如下:
Jedis jedis = null;
try {
    jedis = jedisPool.getResource();
    //具体的命令
    jedis.executeCommand()
} catch (Exception e) {
    logger.error("op key {} error: " + e.getMessage(), key, e);
} finally {
    //注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
    if (jedis != null) 
        jedis.close(); 
}

       拦截器的实现都是基于代理的设计模式实现的,简单的说就是要创造一个目标类的代理类,在代理类中执行目标类的方法并在方法之前执行拦截器代码,拦截器一般有登陆拦截器——验证会话信息,权限拦截器——验证权限信息,那么SqlSessionInterceptor是干什么的?

       Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。打个比方,对于Executor,Mybatis中有几种实现:BatchExecutor、ReuseExecutor、SimpleExecutor和CachingExecutor。
这个时候如果你觉得这几种实现对于Executor接口的query方法都不能满足你的要求,那怎么办呢?是要去改源码吗?当然不。我们可以建立一个Mybatis拦截器用于拦截Executor接口的query方法,在拦截之后实现自己的query方法逻辑,之后可以选择是否继续执行原来的query方法。允许你在已映射语句执行过程中的某一点进行拦截调用。有的用Mybatis拦截器统封装分页,有的用它实现读写分离等,如果读写分离还是建议配置多数据源;

       spring整合mybatis之后,通过动态代理的方式,使用SqlSessionTemplate持有的sqlSessionProxy属性来代理执行sql操作,由spring管理的sqlSeesion在sql方法(增删改查等操作)执行完毕后就自行关闭了sqlSession,不需要我们对其进行手动关闭。

       愿你有情人终成眷属,愿你有个有趣的灵魂,愿你拍我一砖!

转载于:https://www.cnblogs.com/viaiu/p/9346575.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一个流行的Java持久化框架,它提供了一种简单且灵活的方式来访问数据库。MyBatis的配置文件对整个框架的使用产生深远的影响,因此我们需要认真学习它。[1]配置文件中包含了数据库连接信息、映射器配置、SQL语句等重要内容,通过配置文件可以实现对数据库的增删改查操作。 除了配置文件,MyBatis最强大的工具之一是映射器。映射器是用于定义SQL语句和Java方法之间映射关系的工具,我们在使用MyBatis时会经常使用到它。[1]映射器可以将数据库表的字段映射到Java对象的属性上,使得我们可以方便地进行对象与数据库之间的转换。 在实际工作中,我们经常会遇到一些特殊的场景,需要灵活运用MyBatis来解决问题。比如处理数据库的BLOB字段的读写、批量更新、调用存储过程、分页、使用参数作为列名、分表等等。[2]这些场景都是通过实战总结出来的,具有较强的实用价值,可以帮助我们更好地应对实际开发中的需求。 此外,MyBatis和Spring框架的结合也是非常常见的。Spring框架是Java世界最流行的IOC和AOP框架之一,而MyBatis和Spring的结合可以构建高性能的大型网站。[3]通过使用Spring MVC和MyBatis,我们可以充分发挥它们的优势,实现灵活可配置的SQL操作,从而构建高性能的Java互联网应用。 总结起来,深入浅出地学习MyBatis的技术原理和实战经验,可以帮助我们更好地理解和应用这个持久化框架,提高开发效率和代码质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值