`

c3p0代码动态切换数据源

    博客分类:
  • JAVA
阅读更多
public class PARPDatasource implements DataSource, FactoryBean<PARPDatasource> {
private static PARPDatasource parpDatasource = new PARPDatasource();

private static ThreadLocal<String> currrentDatasourceId = new ThreadLocal<String>();

private static Map<String, DataSource> dataSourceStore = new ConcurrentHashMap<String, DataSource>();
private static Log log = LogFactory.getLog(PARPDatasource.class);

public static synchronized void updateDataSource(
Map<String, String> dbSourceInfo) throws Exception {
currrentDatasourceId.set(dbSourceInfo.get("ID_BI_INFO"));
if (!isDataSourceUnchanged(dbSourceInfo)) {
log.info("datasource changed reinit datasourceId="+ getCurrentDataSourceId());
ComboPooledDataSource oldDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
dataSourceStore.put(getCurrentDataSourceId(),
initDataSource(dbSourceInfo));
closeQuietly(oldDataSource);
}
}
public static synchronized void refreshDataSource(
Map<String, String> dbSourceInfo) throws Exception {
log.info("datasource refresh reinit");
currrentDatasourceId.set(dbSourceInfo.get("ID_BI_INFO"));
log.info("datasource refresh reinit datasourceId="
+ getCurrentDataSourceId());
ComboPooledDataSource oldDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
dataSourceStore.put(getCurrentDataSourceId(),
initDataSource(dbSourceInfo));
closeQuietly(oldDataSource);
}
private static void closeQuietly(ComboPooledDataSource oldDataSource) {
log.info("datasource closeQuietly");
if (oldDataSource != null) {
try {
log.info("datasource closeQuietly start");
oldDataSource.close();
log.info("datasource closeQuietly end");
} catch (Exception e) {
log.error("close datasource error:currentDataSourceId="
+ getCurrentDataSourceId(), e);
}
}
}
private static boolean isDataSourceUnchanged(
Map<String, String> dbSourceInfo) {
ComboPooledDataSource currentDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
if (null == currentDataSource) {
return false;
}
return dbSourceInfo.get("JDBC_URL").equals(
currentDataSource.getJdbcUrl())
&& dbSourceInfo.get("USERNAME").equals(
currentDataSource.getUser())
&& dbSourceInfo.get("PASSWORD").equals(
currentDataSource.getPassword());
}

private DataSource getCurrentDataSource() throws SQLException {
try {
return dataSourceStore.get(getCurrentDataSourceId());
} catch (Exception e) {
throw new SQLException(e);
}
}

private static String getCurrentDataSourceId() {
return currrentDatasourceId.get();
}

private static DataSource initDataSource(Map<String, String> dbSourceInfo)
throws Exception {
log.info("datasource initDataSource start");
DriverManager.setLogWriter(new PrintWriter(System.out));
ComboPooledDataSource ds = new ComboPooledDataSource();

ds.setDriverClass(dbSourceInfo.get("DRIVER_CLASS"));
ds.setJdbcUrl(dbSourceInfo.get("JDBC_URL"));
ds.setUser(dbSourceInfo.get("USERNAME"));
ds.setPassword(dbSourceInfo.get("PASSWORD"));
ds.setDataSourceName(dbSourceInfo.get("ID_BI_INFO"));
// 初始化时获取5个连接,取�1�7�应在minPoolSize与maxPoolSize之间。Default: 3
ds.setInitialPoolSize(1);
// 连接池中保留的最大连接数。Default: 15
ds.setMaxPoolSize(70);
// 连接池中保留的最小连接数。Default: 5
ds.setMinPoolSize(1);
ds.setMaxStatementsPerConnection(100);

ds.setNumHelperThreads(5);
// <!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->
ds.setTestConnectionOnCheckout(isNotHiveDriver(dbSourceInfo));
// --因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
// 等方法来提升连接测试的性能。Default: false
ds.setTestConnectionOnCheckin(false);
// 每60秒检查所有连接池中的空闲连接。Default: 0 目前我们测试出来是 milliseconds,0表示 不测试
ds.setIdleConnectionTestPeriod(0);

// 最大空闲时间,30分钟内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 单位 seconds
ds.setMaxIdleTime(30 * 60);
// 当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出
// SQLException,如设为0则无限期等待。单位毫秒。Default: 0
ds.setCheckoutTimeout(180 * 1000);
// 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:
// 测试的表必须在初始数据源的时候就存在。Default: null
if (StringUtils.isNotEmpty(dbSourceInfo.get("TEST_TABLE_QUERY"))){
ds.setPreferredTestQuery(dbSourceInfo.get("TEST_TABLE_QUERY"));
}else{
ds.setPreferredTestQuery("select 1 from dual");
}
//ds.setAcquireRetryAttempts(10);//尝试30次连接
//ds.setAcquireRetryDelay(100);//每100ms尝试一次
ds.setBreakAfterAcquireFailure(true);// 获取连接失败关闭数据源,网络异常需要重启或者重新配置数据源
//ds.setUnreturnedConnectionTimeout(30);//自动超时回收Connection (强烈推荐) default : 0 单位 s
log.info("datasource initDataSource end");//
return ds;

}

private static boolean isNotHiveDriver(Map<String, String> dbSourceInfo) {
boolean flag=true;
  if("org.apache.hive.jdbc.HiveDriver".equals(dbSourceInfo
.get("DRIVER_CLASS"))){
  flag=false;
  }else if("org.postgresql.Driver".equals(dbSourceInfo
.get("DRIVER_CLASS"))){
  flag=false;
 
  }
return flag;
}

@Override
public Connection getConnection() throws SQLException {
log.info("...getConnection..currrentDatasourceId...."+getCurrentDataSourceId());
return getCurrentDataSource().getConnection();

}

@Override
public Connection getConnection(String username, String password)
throws SQLException {
return getCurrentDataSource().getConnection(username, password);
}

@Override
public PARPDatasource getObject() throws Exception {
return parpDatasource;
}

@Override
public Class<PARPDatasource> getObjectType() {
return PARPDatasource.class;
}

@Override
public boolean isSingleton() {
return true;
}

public static PARPDatasource getInstance() {
return parpDatasource;
}

@Override
public PrintWriter getLogWriter() throws SQLException {
return getCurrentDataSource().getLogWriter();
}

@Override
public int getLoginTimeout() throws SQLException {
return getCurrentDataSource().getLoginTimeout();
}

@Override
public void setLogWriter(PrintWriter printWriter) throws SQLException {
getCurrentDataSource().setLogWriter(printWriter);

}

@Override
public void setLoginTimeout(int loginTimeout) throws SQLException {
getCurrentDataSource().setLoginTimeout(loginTimeout);

}

@Override
public boolean isWrapperFor(Class<?> clazz) throws SQLException {
return getCurrentDataSource().isWrapperFor(clazz);
}

@Override
public <T> T unwrap(Class<T> clazz) throws SQLException {
return getCurrentDataSource().unwrap(clazz);
}

public String getDriverClassName() throws Exception {
return ((ComboPooledDataSource) getCurrentDataSource())
.getDriverClass();
}


@SuppressWarnings({"unused", "finally"})
public static boolean  validateDB(Map paramMap) {
Connection conn = null;
try {
log.info("------- validateDB   start -------------");
String userPwdSource = (String) paramMap.get("userPwdSource");
Class.forName((String) paramMap.get("driverClass"));
String pwd = (String) paramMap.get("dbPwd");
if ("cyberark".equals(userPwdSource)) {
pwd=ParpCyberarkUtil.getV9CyberarkPassword(
(String)paramMap.get("requestPowdPath"),
(String) paramMap.get("cyberarkAuthname"),
(String) paramMap.get("cyberarkCredappId"),
(String) paramMap.get("cyberarkPwdKey"),
(String) paramMap.get("cyberarkPwdSafe"),
(String) paramMap.get("cyberarkPwdFolder"),
pwd);

}
DriverManager.setLoginTimeout(60);// 设置超时为1秒
conn = DriverManager.getConnection(
(String) paramMap.get("driverUrl"),
(String) paramMap.get("userName"), pwd);
log.info("------- validateDB connect -------------" + conn);
if (conn != null) {
log.info("------- validateDB  end  true -------------");
return true;
}
} catch (Exception e) {
log.error("validateDB  connect  exception url="
+ paramMap.get("driverUrl") + "&user="
+ paramMap.get("userName"));
log.error(e);
log.info("validateDB error : " + e.getMessage());
log.error(e.getMessage(), e.getCause());
log.info("------- validateDB  connect false -------------", e);
return false;
} finally {
try {
conn.close();
} catch (Exception e) {

}

}
log.info("------- validateDB  end  false -------------");
return false;
}
}
分享到:
评论

相关推荐

    mysql.c3p0配置动态数据源的依赖包

    配置MySQL.C3p0动态数据源的过程通常包括以下几个步骤: 1. 将以上三个JAR文件添加到项目的类路径中,确保在运行时能够找到这些依赖。 2. 在项目中创建配置文件,例如`c3p0.properties`,设置C3p0连接池的属性,如...

    mybatis+spring实现动态切换数据源

    在本项目中,我们将探讨如何利用MyBatis与Spring框架实现动态切换数据源的功能。首先,我们需要理解MyBatis和Spring的基本概念以及它们如何协同工作。 MyBatis是一个优秀的持久层框架,它简化了Java与数据库之间的...

    动态创建和切换数据源

    例如,可以使用Apache DBCP或C3P0等连接池库动态创建数据源,或者利用Spring框架的AbstractRoutingDataSource实现,根据业务条件(如租户ID、环境等)动态决定使用哪个数据源。 4. **切换数据源**:切换数据源通常...

    Spring 动态切换数据源

    【Spring 动态切换数据源】是一种在Spring框架中实现的应用程序能够在运行时根据需求动态选择数据源的技术。这种功能对于多数据库环境或者需要对不同数据源执行操作的系统非常有用,例如数据聚合、报表生成等场景。 ...

    动态切换Datasource

    5. **代码实现**: 实现动态切换数据源需要编写自定义的DataSource类,该类通常会继承Spring的`AbstractRoutingDataSource`。在这个类中,我们需要覆盖`determineCurrentLookupKey`方法,该方法返回当前应该使用的...

    动态创建数据源,加上jar包就可以运行

    常见的数据源实现有Apache Commons DBCP、C3P0、HikariCP等。在Java中,我们通常通过Java的Context和Initial LifeCycle(JNDI)服务或者Spring框架来管理数据源。 动态创建数据源一般涉及以下步骤: 1. **导入依赖...

    c3p0连接池.zip

    3. **连接池扩展性**:C3P0支持多数据源,可以在同一个应用中管理多个数据库连接池,方便进行数据源的切换和负载均衡。 4. **连接池监控**:C3P0提供了详细的监控信息,如连接池状态、连接使用情况等,通过JMX...

    数据源动态配置demo

    - **Druid的DynamicDataSource**:Druid数据源提供了动态数据源功能,支持根据规则自动切换数据源。 - **MyBatis Plus的MultipleDataSource**:MyBatis Plus扩展了MyBatis,提供了多数据源的支持。 4. **动态数据...

    SSM多数据源分包

    为了方便在代码中切换数据源,我们可以使用注解来指定当前操作应使用哪个数据源。例如,可以自定义一个`@UseDataSource`注解,然后在Service方法上使用它,使得SpringAOP可以在运行时解析并应用这个注解。 7. **...

    数据源封装代码jar包

    5. 相关依赖库:如JDBC驱动,连接池实现(如Apache DBCP,C3P0,HikariCP等)。 6. Maven或Gradle构建文件:用于编译和打包项目。 使用这个jar包时,开发者只需要将它引入到他们的项目依赖中,然后在代码中调用预设...

    java 多数据源

    4. **动态切换数据源**:在业务代码中,可以通过AOP(面向切面编程)实现数据源的动态切换。创建一个自定义注解,如`@UseDataSource`,并在方法上使用该注解指定数据源。然后编写AOP切面,解析注解信息并在执行方法...

    MyBatis基于源码的多数据源

    首先,"MyBatis基于源码的多数据源"这个标题暗示了我们将不依赖于第三方库(如Apache的DBCP或C3P0)来处理多数据源,而是直接在MyBatis的源码级别上进行配置和扩展。这种做法的好处是可以更好地控制数据源的选择,...

    SSM框架多数据源的配置

    2. 数据源切换:在运行时,确保根据业务需求正确切换数据源,避免出现数据不一致的问题。 3. 测试验证:完成配置后,务必进行详尽的单元测试和集成测试,确保多数据源功能正常工作。 总结,SSM框架的多数据源配置...

    java多数据源注解方式

    如果需要根据业务逻辑动态切换数据源,可以使用AOP(面向切面编程)和自定义注解。创建一个自定义注解(如`@UseDataSource`),然后编写一个AOP切面,根据注解中的参数或方法上的元数据来决定使用哪个数据源。 7. ...

    Ssh多数据源.doc

    在企业级应用开发中,尤其是大型分布式系统,多数据源管理是常见的需求。...在实际应用中,可以根据业务需求创建更多的数据源bean,并通过编程或配置方式切换数据源,以满足复杂场景下的数据访问需求。

    注解方式-多数据源的案例代码

    每个数据源可以是JDBC的DataSource实例,例如使用Apache的DBCP或C3P0连接池。配置文件中的两个数据源示例如下: ```xml ``` 2. **数据源切换策略** 为了在运行时选择合适的数据源,...

    spring整合多数据源完整实例

    Spring支持多种数据源类型,如Apache的DBCP或C3P0,以及HikariCP等高性能连接池。以下是一个基于HikariCP的数据源配置示例: ```java @Configuration public class DataSourceConfig { @Value("${ds1.jdbc.url}")...

    c3p0-0.9.5-pre7.zip

    c3p0是一个开源的JDBC连接池,全称为com.mchange.v2.c3p0,它实现了数据源和JNDI绑定,提供了一套配置灵活、功能强大的数据库连接池解决方案。c3p0的主要功能包括: 1. **连接池管理**:通过复用已打开的数据库连接...

    Spring管理配置多个数据源

    通常,我们可以使用Apache的DBCP或C3P0这样的第三方库来提供数据源,或者直接使用JDBC的DriverManagerDataSource。Spring通过ApplicationContext中的Bean定义来管理这些数据源。 要配置多个数据源,我们需要创建两...

    轻量级的java数据源jdbc框架

    本文将深入探讨一个轻量级的 Java 数据源框架,该框架基于 C3P0 数据源并采用纯 Java 实现,适用于多种数据库,如 MySQL、Oracle 和 SQL Server。 首先,让我们来了解 C3P0 数据源。C3P0 是一个开源的 JDBC 连接池...

Global site tag (gtag.js) - Google Analytics