mybatis与数据库访问相关的配置以及设计

摘要:
与数据库访问相关的mybatis的配置和设计。无论NB如何,mybatis总是要处理数据库。通过提问的方式,我们可以更深入地了解哪些常用的MyBatis配置与数据库相关//TODO之前没有查看代码:实际的MyBatis设计没有直接返回Connection,而是返回dataSource。2.如何设计具有连接池的数据源和不具有连接池数据源?流程和责任的差异现在我们可以解开谜团了:实际的迈巴斯设计如何?

mybatis与数据库访问相关的配置以及设计

mybatis不管如何NB,总是要与数据库进行打交道。通过提问的方式,逐步深入

  • 我们常用的MyBatis配置中哪些是与数据库相关?
  1. 数据源配置:
1         <environment id="development">
2             <transactionManager type="JDBC"/>
3             <dataSource type="POOLED">
4                 <property name="driver" value="${driver}"/>
5                 <property name="url" value="${url}"/>
6                 <property name="username" value="${username}"/>
7                 <property name="password" value="${password}"/>
8             </dataSource>
9         </environment>

看到这个配置文件,第一个直觉会想到由谁读取配置文件,谁有读取了配置信息?先忽略这个疑问,跳过。直接看下面的问题

  1.配置数据源信息后,由谁来创建、管理数据源?

    根据JDBC驱动中约束的接口,Connection需要DataSource中获取

    如果自己设计,是否直接可以由工厂返回Connection?有什么好处,有什么坏处? //TODO

         没看代码前:

                            mybatis与数据库访问相关的配置以及设计第1张

        实际Mybatis设计,没有直接返回Connection,而返回了dataSource

                                                       mybatis与数据库访问相关的配置以及设计第2张

    2.对于有连接池的数据源,和无连接池的数据源,我们自己会如何设计?

      流程上的区别

                                                mybatis与数据库访问相关的配置以及设计第3张

     职责上区别

                                  mybatis与数据库访问相关的配置以及设计第4张

    现在解开谜底:看实际Mybatis设计如何?

      非池化类:

                      mybatis与数据库访问相关的配置以及设计第5张

看下最关键的,获得数据库连接,和我们自己写的没啥区别。简单粗暴

  private Connection doGetConnection(Properties properties) throws SQLException {
    initializeDriver();
    Connection connection = DriverManager.getConnection(url, properties);
    configureConnection(connection);
    return connection;
  }

    

    池化类:

    mybatis与数据库访问相关的配置以及设计第6张

    池化工作分配  :

  
              mybatis与数据库访问相关的配置以及设计第7张

  至此,MYBABTIS对于数据源的创建以及管理结束!看下代码,池化获得连接的代码

  @Override
  public Connection getConnection() throws SQLException {
    return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();
  }
while (conn == null) { //够用就行,拿到一个就返回
      synchronized (state) {

          //只有有连接还回来,再走这里
        if (!state.idleConnections.isEmpty()) {
          // Pool has available connection
          conn = state.idleConnections.remove(0);
          if (log.isDebugEnabled()) {
            log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
          }
        } else {

        //有两种可能:1种,都在使用中,池子没满,再新建
          // Pool does not have available connection
          if (state.activeConnections.size() < poolMaximumActiveConnections) {
            // Can create new connection

            //新建连接
            conn = new PooledConnection(dataSource.getConnection(), this);
            if (log.isDebugEnabled()) {
              log.debug("Created connection " + conn.getRealHashCode() + ".");
            }
          } else {
            // Cannot create new connection

            //找一个最老的,用的ArrayList,老的在ArrayList数组的前面
            PooledConnection oldestActiveConnection = state.activeConnections.get(0);
            long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();

            //借出超时,不让他做了,直接rollback。。。暴力
            if (longestCheckoutTime > poolMaximumCheckoutTime) {
              // Can claim overdue connection
              state.claimedOverdueConnectionCount++;
              state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
              state.accumulatedCheckoutTime += longestCheckoutTime;
              state.activeConnections.remove(oldestActiveConnection);
              if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
                try {
                  oldestActiveConnection.getRealConnection().rollback();
                } catch (SQLException e) {
                  /*
                     Just log a message for debug and continue to execute the following
                     statement like nothing happend.
                     Wrap the bad connection with a new PooledConnection, this will help
                     to not intterupt current executing thread and give current thread a
                     chance to join the next competion for another valid/good database
                     connection. At the end of this loop, bad {@link @conn} will be set as null.
                   */
                  log.debug("Bad connection. Could not roll back");
                }  
              }

              //拿回来后,不再放到原有的PooledConnection,新建立一个。从新开始.老的REAL connection还被oldestActiveConnection引用,不会内存溢出?
              conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
              conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
              conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
              
              oldestActiveConnection.invalidate();
              if (log.isDebugEnabled()) {
                log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
              }
            } else {
              // Must wait

                //大家都在用着,你只能等着了。
              try {
                if (!countedWait) {
                  state.hadToWaitCount++;
                  countedWait = true;
                }
                if (log.isDebugEnabled()) {
                  log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
                }
                long wt = System.currentTimeMillis();
                state.wait(poolTimeToWait);
                state.accumulatedWaitTime += System.currentTimeMillis() - wt;
              } catch (InterruptedException e) {
                break;
              }
            }
          }
        }
        if (conn != null) {
          // ping to server and check the connection is valid or not
          if (conn.isValid()) {
            if (!conn.getRealConnection().getAutoCommit()) {
              conn.getRealConnection().rollback();
            }
            conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));
            conn.setCheckoutTimestamp(System.currentTimeMillis());
            conn.setLastUsedTimestamp(System.currentTimeMillis());
            state.activeConnections.add(conn);
            state.requestCount++;
            state.accumulatedRequestTime += System.currentTimeMillis() - t;
          } else {
            if (log.isDebugEnabled()) {
              log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
            }
            state.badConnectionCount++;
            localBadConnectionCount++;
            conn = null;

            //如果累计有这些个链接失效了,则报个异常.
            if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {
              if (log.isDebugEnabled()) {
                log.debug("PooledDataSource: Could not get a good connection to the database.");
              }
              throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
            }
          }
        }
      }

    }

        

    

  

 

免责声明:文章转载自《mybatis与数据库访问相关的配置以及设计》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux下统计代码行数验证码识别,发票编号识别下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

mybatis generator 生成带中文注释的model类

将org.mybatis.generator.interal.DefaultCommentGenerator类的addFieldComment方法重写,代码如下: public void addFieldComment(Field field, IntrospectedTable introspectedTable,...

使用Mybatis-Plus的一个坑

问题描述 在使用Mybatis-Plus的过程中,突然发生这样一个错误。 *************************** APPLICATION FAILED TO START *************************** Description: An attempt was made to call a method that d...

mybatisplus使用

在mapper层创建StudentMapper接口并继承BaseMapper接口 MyBatis和Mybatis Plus的使用比较 MybatisPlus包含了Mybatis的所有功能,也就说在MybatisPlus中我们仍然可以按照Mybatis的方式来完成数据库的操作(无侵入)。 MybatisPlus的数据库操作的Mapper层的接口只需要继承B...

Spring Boot整合Mybatis配置详解

首先,你得有个Spring Boot项目。 平时开发常用的repository包在mybatis里被替换成了mapper。 配置: 1.引入依赖: <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-s...

mysql 动态拼接表字段,值 mybatis 动态获取表字段

-- 取表所有字段,自动用逗号分开 select GROUP_CONCAT(DISTINCT COLUMN_NAME) from information_schema.columns where table_name='tb1'结果集:  字段1,字段2,字段3,字段4..... -- 动态拼接字段,给mybatis用 某些业务情况下没有去使用自动生成代...

mybatis教程:入门&amp;gt;&amp;gt;精通&amp;gt;&amp;gt;实战

以前曾经用过ibatis,这是mybatis的前身,当时在做项目时,感觉很不错,比hibernate灵活。性能也比hibernate好。而且也比较轻量级,因为当时在项目中,没来的及做很很多笔记。后来项目结束了,我也没写总结文档。已经过去好久了。但最近突然又对这个ORM 工具感兴趣。因为接下来自己的项目中很有可能采用这个ORM工具。所以在此重新温习了一下 m...