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

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

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

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

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

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

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

         没看代码前:

                            

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

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

      流程上的区别

     职责上区别

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

      非池化类:

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

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

    

    池化类:

    

    池化工作分配  :

  至此,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与数据库访问相关的配置以及设计的更多相关文章

  1. SpringBoot:4.SpringBoot整合Mybatis实现数据库访问

    在公司项目开发中,使用Mybatis居多.在 SpringBoot:3.SpringBoot使用Spring-data-jpa实现数据库访问 中,这种jpa风格的把sql语句和java代码放到一起,总 ...

  2. mysql+spring+mybatis实现数据库读写分离[代码配置] .

    场景:一个读数据源一个读写数据源. 原理:借助spring的[org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource] ...

  3. Spring Mvc和Mybatis的多数据库访问配置过程

    Spring Mvc 加Mybatis的多数据库访问源配置访问过程如下: 在applicationContext.xml进行配置 <?xml version="1.0" en ...

  4. Spring+MyBatis实践—MyBatis数据库访问

    关于spring整合mybatis的工程配置,已经在Spring+MyBatis实践—工程配置中全部详细列出.在此,记录一下几种通过MyBatis访问数据库的方式. 通过sqlSessionTempl ...

  5. 使用MyBatis搭建一个访问mysql数据库的简单示例

    MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用 ...

  6. Spring+MyBatis双数据库配置

    Spring+MyBatis双数据库配置 近期项目中遇到要调用其它数据库的情况.本来仅仅使用一个MySQL数据库.但随着项目内容越来越多,逻辑越来越复杂. 原来一个数据库已经不够用了,须要分库分表.所 ...

  7. Spring+Mybatis+Mysql搭建分布式数据库访问框架

    一.前言 用Java开发企业应用软件, 经常会采用Spring+MyBatis+Mysql搭建数据库框架.如果数据量很大,一个MYSQL库存储数据访问效率很低,往往会采用分库存储管理的方式.本文讲述如 ...

  8. spring配置druid连接池和监控数据库访问性能

    Druid连接池及监控在spring配置如下: <bean id="dataSource" class="com.alibaba.druid.pool.DruidD ...

  9. SpringBoot入门 (四) 数据库访问之JdbcTemplate

    本文记录在SpringBoot中使用JdbcTemplate访问数据库. 一 JDBC回顾 最早是在上学时接触的使用JDBC访问数据库,主要有以下几个步骤: 1 加载驱动 Class.forName( ...

随机推荐

  1. C#字符串的CompareTo比较,让我疑惑的地方

    在学习选择排序算法的时候,用到CopareTo方法.由于比较的数字,是自己随意输入的. 当我输入字符串“8”,它和字符串“16”比较时候. string str1 = "8"; s ...

  2. linux 保存git的账号密码

    今天在弄jenkins一建发版,遇到了git下载每次都要输入账号密码,所以百度一下,使用一下方法,搞定 一.通过文件方式 1.在~/下, touch创建文件 .git-credentials, 用vi ...

  3. mysql 导入数据库问题

    今天数据库迁移测试,发现存储过程导入不了,提示如下错误: Cannot load from mysql.proc. The table is probably corrupted 原因是mysql5. ...

  4. postman Could not get any response。

    浏览器输入地址可以返回结果,但是由于返回的json没有格式,看起来比较麻烦,用postman却报错Could not get any response. 可以注意到下面写了可能的情况:比如服务器无响应 ...

  5. windows下配置maven

    首先下载好maven的压缩包,然后解压到某个目录下,我解压到了D盘 打开readme.txt 1.2步已经完成,第3步的意思是让我们把bin所在的路径添加到系统变量的path中去 第4步意思是确保的你 ...

  6. Java面试3

    反射的定义: 反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取它所有的成员变量和方法并且显示出来. 反射机制的 ...

  7. 设置table的每竖的宽度

  8. SSH配置

    什么是SSH: SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定:SSH 为建立在应用层和传输层基础上的安全协议.SSH ...

  9. jmeter简单的接口性能测试

    原文转自:https://blog.csdn.net/lovesoo/article/details/78579547 Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件 ...

  10. IPFS 探索

    IPFS 探索 比特币当前是用于存金融交易数据,有leveldb 存关键小的交易数据.那么我们的文件,譬如一个网站里面的static file 怎么办? IPFS(InterPlanetary Fil ...