mybatis中的数据源和连接池
1、核心配置文件中配置数据库相关属性
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--environments是环境配置,是复数说明下面可以配置多个环境
所以default属性的值表示这个配置文件用下面的哪一套数据库配置信息
这里使用development1
-->
<environments default="development1">
<!--第一套数据库连接信息配置,唯一标识id叫development-->
<environment id="development1">
<!--transactionManager:表示mybatis提交事务和回滚事务的方式
type:事务的处理类型:
1、填JDBC 表示mybatis底层是调用JDBC规范中的Connection对象进行事务提交与回滚的
2、填MANAGED 表示mybatis把事务委托给其他容器处理(一个服务器软件,或者是一个框架(spring))
-->
<transactionManager type="JDBC"/>
<!--dataSource:表示使用的数据源类型,Java中,实现了javax.sql.DataSource接口
的都可以当作数据源,数据源就是Connection对象
type:指定数据源类型
POOLED:表示mybatis到连接池中获取Connection对象,即使用连接池,创建PooledDataSource类对 象
UNPOOLED:不使用连接池,mybatis每次执行sql语句,创建一个Connection对象,执行完后将 Connection对象释放,mybatis创建的是UnPooledDataSource类对象
JNDI:是一个java命名和目录(相当于Windows注册表,了解就好)
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<mappers>
<!--这里也可以添加多个sql映射文件,因为项目中不止一个表
这就是映射文件中namespace属性的作用了-->
<!-- <mapper resource="StudentDao.xml"/>-->
<mapper resource="com/studymyself/dao/UserDao.xml"/>
</mappers>
</configuration>
2、mybatis中的数据源和连接池
上面的核心配置文件中,数据源的选择类型有三种,其中前两种需要我们掌握
--连接池
mybatis中实现了javax.sql.DataSource规范,该规范中有许多获取Connection对象的方法,有两个实现类:
PooledDataSource和UnPooledDataSource
其中实现类PooledDataSource是可以创建多个Connection对象,以队列的形式存到集合中,先存先被取出。当一个线程需要连接对象使直接从该集合中取出最先存的一个,另一个线程需要时又取出第二存进去的一个,线程结束后将这个连接对象放回集合中,排到后面。这个集合就是线程池,而且是线程安全的,不允许一个Connection对象被两个线程获取。
--这种数据源的方式是实际开发中使用的,极大的减少了获取连接对象的时间
实现类UnPooledPooledDataSource,该类中的方法是在需要的时候获取创建Connection对象,完成线程任务后释放掉。一般开发中我们只是在测试阶段使用。
实现类PooledDataSource代码片段
public class PooledDataSource implements DataSource {
private static final Log log = LogFactory.getLog(PooledDataSource.class);
private final PoolState state = new PoolState(this);
private final UnpooledDataSource dataSource;
protected int poolMaximumActiveConnections = 10;
protected int poolMaximumIdleConnections = 5;
protected int poolMaximumCheckoutTime = 20000;
protected int poolTimeToWait = 20000;
protected int poolMaximumLocalBadConnectionTolerance = 3;
protected String poolPingQuery = "NO PING QUERY SET";
protected boolean poolPingEnabled;
protected int poolPingConnectionsNotUsedFor;
private int expectedConnectionTypeCode;
public PooledDataSource() {
this.dataSource = new UnpooledDataSource();
}
public PooledDataSource(UnpooledDataSource dataSource) {
this.dataSource = dataSource;
}
public PooledDataSource(String driver, String url, String username, String password) {
this.dataSource = new UnpooledDataSource(driver, url, username, password);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
public PooledDataSource(String driver, String url, Properties driverProperties) {
this.dataSource = new UnpooledDataSource(driver, url, driverProperties);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {
this.dataSource = new UnpooledDataSource(driverClassLoader, driver, url, username, password);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
this.dataSource = new UnpooledDataSource(driverClassLoader, driver, url, driverProperties);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
public Connection getConnection() throws SQLException {
return this.popConnection(this.dataSource.getUsername(), this.dataSource.getPassword()).getProxyConnection();
}
public Connection getConnection(String username, String password) throws SQLException {
return this.popConnection(username, password).getProxyConnection();
}
...
实现类UnPooledPooledDataSource代码片段
public class UnpooledDataSource implements DataSource {
private ClassLoader driverClassLoader;
private Properties driverProperties;
private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap();
private String driver;
private String url;
private String username;
private String password;
private Boolean autoCommit;
private Integer defaultTransactionIsolationLevel;
private Integer defaultNetworkTimeout;
public UnpooledDataSource() {
}
public UnpooledDataSource(String driver, String url, String username, String password) {
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
}
public UnpooledDataSource(String driver, String url, Properties driverProperties) {
this.driver = driver;
this.url = url;
this.driverProperties = driverProperties;
}
public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {
this.driverClassLoader = driverClassLoader;
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
}
public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
this.driverClassLoader = driverClassLoader;
this.driver = driver;
this.url = url;
this.driverProperties = driverProperties;
}
public Connection getConnection() throws SQLException {
return this.doGetConnection(this.username, this.password);
}
public Connection getConnection(String username, String password) throws SQLException {
return this.doGetConnection(username, password);
}
...
3、数据库连接池和connection的理解
数据库连接池Data Source Pool的理解
1.数据库连接池允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个连接,避免了每个方法里new connection的耗费资源和时间。
2.数据库连接池是在项目启动时候初始化的,以方便程序运行时,随时可以调用这些已经被创建好的connection。只需要getConnection()就好。
connection的建立、断开都由连接池自身来管理。
3.创建connection是个很耗时的操作,所以建议在项目启动的时候去创建connection。避免在方法里需要connection时再去new一个connection是很耗费时间的。
4.数据库连接池,怎样归还connection?
Connection connection = pool.getConnection();
pool.release(connection);//归还资源
5.程序启动时候,是怎样初始化一个数据连接池的?
答:spring启动会自动ioc注入bean,相当于new已经配置好的连接池类。连接池类里面声明了static的list,用以装放connection。然后通过static代码块来将conection add进这个list。这样,整个list就在new bean的时候,在加载这个连接池类的时,就先创建好了。后期程序运行时候,那些connection就已经存在了。
connection的理解
1.jdbc connection就是一个连接数据库的TCP实例。
2.connection是个长连接的TCP。不像hTTP是个短连接的,每次都要3次握手才能建立。
3.connection长连接是提高了性能。不过还有一些细节的问题需要解决,即mysql发现一个链接长时间没有执行查询请求,就会自动断掉这个连接。
4.具体多长时间后断掉,有个timeout设置时间。通过sql:"show global variables like '%timeout';" 查看。
当链接已经失效了,仍然去执行查询操作,一个明显的表现形式就是提示:MySQL server has gone away
5.数据库连接池通过心跳机制,每间断一段时间发送空数据包来保持维护connection存活的。
6.长连接适用于要进行大量数据传输的情况,如:数据库,redis,memcached等要求快速,数据量大的情况下。
7.我们平常用的数据库连接都是长连接的,因为我们每次都是从数据库连接池中去拿connection的!!!db source里都是长连接!!
8.mysql默认的connection timeout时间是8小时。这个可以通过my.ini配置文件修改。
9.connection不是线程安全的!Connection不是线程安全的,它在多线程环境中使用时,会导致数据操作的错乱,特别是有事务的情况.connection.commit()方法就是提交事务,你
可以想象,在多线程环境中,线程A开启了事务,然后线程B却意外的commit,这该是个多么纠结的情况.
10.多个线程同用一个connection会不会提高效率,减少多次连接的消耗?答:不会,因为connection里,每个方法都是synchronized,都执行了同步。所以并不会提高效率。
如:
public int executeUpdate(){
synchronized(connection){
//do
}
}
11.菜鸟一般都是两种方法使用connection:1。要么就是只用一个connection,多个线程都用一个connection。2.要么就是每个方法里面创建一个connection,每次调用都创建
一个connection。
这两种都是效率低下的。
因为TCP链接的创建开支是昂贵的,当然DB server所能承载的TCP并发连接数也是有限制的.因此每次调用都创建一个Connection,这是不现实的;所以才有了数据库连接池的出现.
创建一个数据库连接池:
public class SimplePoolDemo {
//创建一个连接池
private static LinkedList<Connection> pool = new LinkedList<Connection>();
//初始化10个连接
static{
try {
for (int i = 0; i < 10; i++) {
Connection conn = DBUtils.getConnection();//得到一个连接
pool.add(conn);
}
} catch (Exception e) {
throw new ExceptionInInitializerError("数据库连接失败,请检查配置");
}
}
//从池中获取一个连接
public static Connection getConnectionFromPool(){
return pool.removeFirst();//移除一个连接对象
}
//释放资源
public static void release(Connection conn){
pool.addLast(conn);
}
}
4、指定多个mapper文件
当我们一个项目中需要的mapper文件很多时,在标签中添加太多的标签来指定各个接口的映射文件非常繁琐,所以我们可以直接指定这些mapper文件的包名,就可直接将包下的mapper文件全部配置到mybatis中了,具体实现和要求如下所示:
mybatis中的数据源和连接池的更多相关文章
- Mybatis原理之数据源和连接池
在Java工程项目中,我们常会用到Mybatis框架对数据库中的数据进行增删查改,其原理就是对 JDBC 做了一层封装,并优化数据源的连接. 我们先来回顾下 JDBC 操作数据库的过程. JDBC 操 ...
- 阶段3 1.Mybatis_07.Mybatis的连接池及事务_4 mybatis中使用unpooled配置连接池的原理分析
把之前的CRUD的代码src下的代码都复制过来 依赖项也都复制过来, 配置文件 整理一番 执行findAll方法的测试 查看日志的输出部分 修改程序池 再来执行findAll方法 Plooled从连接 ...
- .Net中如何使用MySql连接池
提供一份官方的译文.翻译也挺辛苦的!! 6.4 Using Connector/Net with Connection Pooling 6.4在Connector/Net中使用连接池 The Conn ...
- 在MyBatis中查询数据、涉及多参数的数据访问操作、插入数据时获取数据自增长的id、关联表查询操作、动态SQL、关于配置MyBatis映射没有代码提示的解决方案
1. 单元测试 在单元测试中,每个测试方法都需要执行相同的前置代码和后置代码,则可以自定义2个方法,分别在这2个方法中执行前置代码和后置代码,并为这2个方法添加@Before和@After注解,然后, ...
- 一、DAO设计模式 二、DAO设计模式的优化 三、JDBC中的事务,连接池的使用
一.DAO设计模式概述###<1>概念 DAO,Data Access Object ,用于访问数据库的对象. 位于业务逻辑和数据持久化层之间,实现对数据持久化层的访问 ...
- Spring Boot为我们准备了最佳的数据库连接池方案,只需要在属性文件(例如application.properties)中配置需要的连接池参数即可。
Spring Boot为我们准备了最佳的数据库连接池方案,只需要在属性文件(例如application.properties)中配置需要的连接池参数即可.
- 阶段3 1.Mybatis_07.Mybatis的连接池及事务_5 mybatis中使用poolead配置连接的原理分析
idelConnection是空闲的链接 idelConnection就是ArrayList的数组 如果没有空闲的就new一个 新的connection 一个空闲池,一个活动的池,一个链接过来.空闲池 ...
- springboot整合mybatis使用阿里(阿里连接池)和xml方式
源码地址:https://github.com/wuhongpu/springboot-mybatis.git 1.在pom文件中引入相关依赖包 <?xml version="1.0& ...
- SpringMVC+Spring+Mybatis整合,使用druid连接池,声明式事务,maven配置
一直对springmvc和mybatis挺怀念的,最近想自己再搭建下框架,然后写点什么. 暂时没有整合缓存,druid也没有做ip地址的过滤.Spring的AOP简单配置了下,也还没具体弄,不知道能不 ...
- spark streaming将处理结果存入mysql中(使用c3p0连接池)
1.c3p0相应的架包导入工程中 将以下四个架包导入工程, 主要有三个架包:c3p0-0.9.5.2.jar c3p0-oracle-thin-extras-0.9.5.2.jar mchange-c ...
随机推荐
- 2.11 Linux四种远程管理协议
提到远程管理,通常指的是远程管理服务器,而非个人计算机.个人计算机可以随时拿来用,服务器通常放置在机房中,用户无法直接接触到服务器硬件,只能采用远程管理的方式. 远程管理,实际上就是计算机(服务器)之 ...
- 2023年10月,红米(小米)note 8 pro 优化记
看了红米的note 13 pro和note 12 turbo的参数和价格后,我决定下单买个note8 pro的手机壳,确实有新手机的感觉了. 我note8 pro手机参数如下 MIUI 12.0.5 ...
- 答题判题程序题目集 1~3 的总结性 Blog
前言 1.1 题目集概述 答题判题程序 - 1: 字符串解析:题目内容和答题内容都是按照特定格式给出的字符串,程序需要能正确地拆分和解析这些字符串,然后进行匹配. 对象和类的使用:为了更好地管理题目和 ...
- (Redis基础教程之十) 如何在Redis中运行事务
介绍 Redis是一个开源的内存中键值数据存储.Redis允许您计划一系列命令,然后一个接一个地运行它们,这一过程称为_transaction_.每个事务都被视为不间断且隔离的操作,以确保数据完整性. ...
- HTTP请求与响应格式解析
HTTP是Web浏览器与Web服务器之间通信的标准协议,HTTP指明了客户端如何与服务器建立连接,如果从服务器请求数据,服务器如何响应请求,关闭连接.HTTP是使用TCP/IP协议进行传输数据的,也 ...
- CAD快速图层孤立、隐藏、锁定下载
AutoCAD快速图层孤立.隐藏.锁定插件下载 链接 AutoCAD Quick Layer Isolation, Hide, Lock Plugin Download Link MAG.fas&am ...
- Vue.js 组件基础
1.前言 本节讲述vue组件的基本格式以及实际开发的应用场景,本节内容兼容Vue2.x与Vue3.x 2.组件基础 组件的本质其实就是一个对象,这个对象包含多个属性,常见的属性有:template/d ...
- Element-UI 调整
1.对话框 当打开的对话框页面元素众多,俨然一个iframe页面时,可以做2个优化: 滚动条:对话框去滚动,当对话框内容过多时,把滚动条控制在对话框内部,避免出现页面级的滚动条 标题栏:优化对话框标题 ...
- Java并发 —— 线程并发(一)
线程和进程 进程就是一个内存中运行的应用程序 线程是当前进程中的一个执行任务(控制单元),负责当前进程中程序的执行 区别与联系 根本区别:进程是操作系统资源分配的基本单位,线程是处理器任务调度和执行的 ...
- 规模法则(Scaling Law)与参数效率的提高,
上一篇:<人工智能大语言模型起源篇(三),模型规模与参数效率> 规模法则与效率提高 如果你想了解更多关于提高变换器效率的各种技术,我推荐阅读2020年的<Efficient Tran ...