package com.yunchow.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
/**
* 自定义数据源
* @author yunchow
* @version 1.2 09/8/6
*/
public class MyDataSource {
private static final String DRIVER_CLASS_NAME;
private static final String URL;
private static final String USER;
private static final String PASSWORD;
private static final int INIT_CONNECTION;
private static final int MAX_CONNECTION;
private static final int MAX_IDLE_CONNECTION;
/** 当前连接数 **/
private static int currentConnection = 0;
/** 连接缓冲池 */
private static final LinkedList<Connection> pool;
/** 正在等待连接的线程个数 **/
private static int waitCount = 0;
static {
DRIVER_CLASS_NAME = JdbcConfigBean.getInstance().getProperty("driver");
URL = get("url");
USER = get("user");
PASSWORD = get("password");
String init = get("initConnection");
if(init != null)
INIT_CONNECTION = Integer.parseInt(init);
else
INIT_CONNECTION = 5;
String max = get("maxConnection");
if(max != null)
MAX_CONNECTION = Integer.parseInt(max);
else
MAX_CONNECTION = 10;
String idle = get("idleConnection");
if(idle != null)
MAX_IDLE_CONNECTION = Integer.parseInt(idle);
else
MAX_IDLE_CONNECTION = INIT_CONNECTION;
pool = new LinkedList<Connection>();
try {
// 加载驱动
Class.forName(DRIVER_CLASS_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public MyDataSource() {
for(int i=0; i<INIT_CONNECTION; i++) {
currentConnection ++;
pool.addLast(createConnectionProxy());
}
new PoolScan().start(); // 启动后台线程,扫描连接池
}
/**
* 扫描当前池里的空闲线程,并将其释放
*/
private class PoolScan extends Thread {
public void run() {
try {
while(true) {
//System.out.print("当前连接数: " + pool.size());
//System.out.println("\t最多空闲数: " + MAX_IDLE_CONNECTION);
Thread.sleep(3000); // 每一秒扫描一次连接池
if(pool.size() > MAX_IDLE_CONNECTION) {
//System.out.println("发现多于的空闲连接");
for(int i=0; i<pool.size()-MAX_IDLE_CONNECTION; i++) {
((DBSourceRelease)pool.removeFirst()).release(); // 释放连接
currentConnection --; // 将当前可用连接数减一
System.out.println("Thread-daemo : release();");
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
private static Connection createConnectionProxy() {
Connection proxy = null;
// System.out.println("createConnectionProxy");
try {
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
// System.out.println("xxxxxxxx"+conn);
proxy = new MyConnection(conn).getProxy();
} catch(Exception ex) {
throw new ExceptionInInitializerError(ex);
}
return proxy;
}
private static String get(String arg) {
return JdbcConfigBean.getInstance().getProperty(arg);
}
/**
* 从缓冲池中获取一个连接,如果连接还没有达到最大的连接数,便等待
* 如果还等不到,就抛出数据库异常
*/
public Connection getConnection() throws SQLException {
if(pool.size() > 0) {
synchronized(pool) {
if(pool.size()>0)
return pool.removeFirst();
}
} else if(currentConnection < MAX_CONNECTION) {
currentConnection ++;
return createConnectionProxy();
} else if(currentConnection == MAX_CONNECTION) {
synchronized(pool) {
try {
waitCount ++;
//System.out.println("wait .... ");
pool.wait();
if(pool.size()>0)
return pool.removeFirst();
} catch(Exception ex) {
throw new SQLException("MyDataSource : timeout ");
}
}
throw new SQLException("MyDataSource : timeout ");
}
throw new SQLException("MyDataSource : no more connection ");
}
/**
* 归还连接, 同时还要唤醒正在等待中的线程
*
*/
public static void rebackConnection(Connection conn) {
synchronized(pool) {
pool.addLast(conn);
if(waitCount > 0) {
pool.notifyAll();
//System.out.println("notifyAll .... ");
}
}
}
}
分享到:
相关推荐
在Spring Boot中,AOP(面向切面编程)和多数据源的整合是常见的应用场景,尤其是在大型企业级项目中,为了实现数据的隔离或者优化数据库访问,常常需要配置多个数据源。本文将深入探讨如何使用Spring Boot的AOP注解...
本示例主要讲解如何使用Spring Boot结合MyBatis实现多数据源切换,并确保AOP事务管理仍然有效。 首先,我们需要配置多数据源。在Spring Boot中,可以使用`DataSource`接口的实现类,如`HikariCP`或`Druid`,创建两...
通过这样的方式,Spring的动态数据源实现为开发者提供了极大的便利,使得在多数据库环境中编写代码变得更加简单和灵活。在实际项目中,我们还可以结合Spring的事务管理、AOP切面等特性,实现更加复杂的数据源切换...
总结起来,使用`ThreadLocal`和`AbstractRoutingDataSource`实现动态数据源切换的关键步骤包括: 1. 创建`ThreadLocal`实例来保存线程的数据源信息。 2. 实现`AbstractRoutingDataSource`,并重写`...
本文将深入探讨如何使用MyBatis-Plus优雅地实现多数据源及分表策略,为系统的高效运行提供支持。 首先,多数据源是指在一个应用中同时连接并操作多个不同的数据库,这种设计模式常用于分布式系统或高可用架构中,以...
SpringBoot通过其强大的依赖注入机制和配置模型,使得多数据源的配置变得简单。 在SpringBoot项目中集成Druid,首先需要在`pom.xml`文件中添加Druid的依赖。Druid的最新版本通常可以在Maven仓库中找到,确保添加的...
Spring Boot以其强大的自动化配置能力,使得设置多数据源变得相对简单。接下来,我们将详细讨论如何在Spring Boot中配置多个数据源。 首先,我们需要理解数据源的概念。数据源(DataSource)是Java中用于存储和管理...
除了简单的数据检索,数据源控件还支持插入、更新和删除操作。例如,GridView配合EditItemTemplate和DeleteItemTemplate,可以实现数据的编辑和删除功能,而这一切都通过数据源控件自动处理。 6. **分页和排序** ...
本文将深入探讨如何在Spring MVC项目中实现多数据源的动态切换,以Oracle数据库为例。 首先,我们需要在配置文件中定义多个数据源。在Spring中,我们可以使用`DataSource`接口的实现类,如Apache的`BasicDataSource...
本项目围绕“Java简单分布式架构,多个数据源,线程池多线程访问”这一主题展开,旨在通过利用Java技术栈实现一个高效的分布式系统。 首先,我们关注的是“分布式”这一概念。分布式系统是由多台计算机通过网络连接...
通过理解这些知识,你可以根据实际需求在Delphi 7项目中灵活地添加、修改或删除ODBC数据源,实现与不同数据库系统的无缝连接。注意,实际使用时,应根据具体数据库驱动程序的要求调整配置参数,并进行充分的错误处理...
本文将详细探讨如何在SpringBoot 3.2.3环境下集成ShardingSphere 5.4.1库,实现动态数据源的配置与切换,同时解决兼容性问题,以便支持Oracle(CK)和MySQL等多种数据库。 首先,SpringBoot以其简洁的配置和快速...
主数据源和从数据源的配置都是基于`DriverManagerDataSource`,这是一个简单的数据源实现,适合开发和测试环境。在生产环境中,通常会使用更高效的连接池,如HikariCP、Druid或Apache DBCP。 在实际项目中,数据源...
本教程将详细介绍如何在Spring Boot项目中整合Druid数据源池与Mybatis,实现多数据源切换的功能,并提供一个亲测可用的解决方案。 首先,让我们了解Spring Boot、Druid和Mybatis这三大组件的基础知识: **Spring ...
本篇将详细介绍两种在Spring Boot中实现多数据源的方法:静态添加和动态添加。 **一、静态添加数据源** 静态添加数据源是在配置文件(如application.properties或application.yml)中预先定义好多个数据源的配置。...
通过以上方式,你可以实现Quartz定时任务结合动态切换数据源的功能,使得你的应用程序能够更好地适应复杂的数据库环境,提高系统的稳定性和可扩展性。在提供的压缩包中,readme.txt可能包含了关于如何配置和使用这些...
本文将详细探讨SpringBoot如何实现多数据源以及分布式事务。 首先,我们要理解什么是多数据源。多数据源意味着一个应用可以同时连接和操作多个数据库。在SpringBoot中,我们可以通过配置不同的DataSource Bean来...
数据源(DataSource)在Spring中的配置对于实现持久层操作至关重要。 #### 二、Spring中的数据源配置方式 Spring框架支持多种数据源的配置方式,包括但不限于基于XML的配置、基于注解的配置以及基于Java配置的方式...