使用场景:
在功能元数据管理中需要根据自定义的数据源进行连接,从而在该数据源下面进行增删改查的相关操作,采用Druid连接池根据数据库里面存储的数据源信息动态连接数据库。
实现方式如下:
首先获取数据库的连接信息如下:
Database db=databaseser.get(ysjjbxxyh.getSjysjId());//Database 为自定义的数据库对象
然后进行SQL操作,如下所示:
DruidDataSource druiddatasource=DataSourceTools.createDataSource(db);//获取连接池连接
Connection connection = druiddatasource.getConnection();//获取连接
Statement statement = connection.createStatement();
String[] sql=delsql.split(";");
for(int i=0;i<sql.length;i++){
statement.addBatch(sql[i]);
}
statement.executeBatch();
statement.close();
connection.close();//关闭连接
DataSourceTools方法为进行链接的工具类,如下所示:
package com.inspur.tax.ysjgl.util;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.stat.DruidDataSourceStatManager;
import com.inspur.tax.ysjgl.util.object.data.Database;
/**
* 连接池相关系统监测
* @author admin
*
*/
public class DataSourceTools {
/**
* 获取当前连接池信息
* @param dsName
* @return
*/
public static DruidDataSource getDataSource(String dsName){
DruidDataSource ds = null ;
for(DruidDataSource datasource : DruidDataSourceStatManager.getDruidDataSourceInstances()){
if(dsName.equals(datasource.getName())){
ds = datasource ;
break;
}
}
return ds ;
}
/**
* 获取当前连接池信息
* @param dsName
* @return
*/
public static Map<String,Object> getDataSourceStat(String dsName){
DruidDataSource ds = getDataSource(dsName) ;
return ds!=null ? ds.getStatData() : new HashMap<String , Object>() ;
}
/**
* 创建数据库连接池
* @param database
* @return
* @throws SQLException
* @throws NoSuchAlgorithmException
*/
public static DruidDataSource createDataSource(Database database) throws SQLException, NoSuchAlgorithmException{
DruidDataSource dataSource = null ;
String dsName = database.getId() ;
if((dataSource = getDataSource(dsName))==null){
if("jndi".equals(database.getConnctiontype())){ //判断下是否是 JNDI,如果是JNDI,就直接用 JndiDataSource 来创建, new JndiDataSource
dataSource = new JndiDataSource(database);
dataSource.setName(dsName);
DruidDataSourceStatManager.addDataSource(dataSource , dsName) ;
}else{
dataSource = new DruidDataSource();
dataSource.setName(dsName) ;
dataSource.setUrl(database.getDatabaseurl());
dataSource.setDriverClassName(database.getDriverclazz());
dataSource.setUsername(database.getAccount());
dataSource.setPassword(database.getPassword());
dataSource.setInitialSize(5);
dataSource.setMinIdle(5);
dataSource.setMaxActive(5);
dataSource.setMaxWait(6000) ;
dataSource.setMinEvictableIdleTimeMillis(300000) ;
dataSource.setRemoveAbandoned(false);//超过时间限制是否回收
dataSource.setRemoveAbandonedTimeout(180);//超过时间限制多长
dataSource.setTimeBetweenEvictionRunsMillis(60000);//配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
dataSource.setTestWhileIdle(true);
dataSource.setTestOnBorrow(false) ;
dataSource.setTestOnReturn(false) ;
dataSource.setPoolPreparedStatements(true) ;
dataSource.setMaxPoolPreparedStatementPerConnectionSize(20) ;
dataSource.setValidationQuery("SELECT 1 from dual") ;
dataSource.setTimeBetweenLogStatsMillis(3600000) ;
dataSource.addConnectionProperty("remarksReporting", "true");
//sql中有中文会报错,所以在此注释掉 stat监控统计用 wall防sql注入 log4j日志
//dataSource.setFilters("stat,wall");
//dataSource.setFilters("stat");
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("SELECT 1 from dual") ;
String schema = null ;
Properties properties = ParamTools.getProperties(ParamTools.getProperties(null , database.getConnectparam() , database.getAccount()),database.getConnectparam(),database.getAccount()) ;
if(properties!=null && properties.get("schema")!=null && schema==null){
schema = properties.get("upcase")!=null?((String)properties.get("schema")).toUpperCase():(String)properties.get("schema") ;
}
if(schema!=null && schema.equals("hive")){
statement = connection.createStatement() ;
if(properties.get("database")!=null){
statement.execute("USE "+properties.get("database")) ;
}
statement.close() ;
}
result.close();
statement.close();
connection.close();
}
}
return dataSource;
}
/**
* 关闭数据库连接池
* @param dsName
*/
public static void closeDataSource(String dsName){
getDataSource(dsName).close() ;
}
}
连接池的意义和作用:
建立数据库连接是相当耗时和耗费资源的,而且一个数据库服务器能够同时建立的连接数也是有限的,在大型的Web应用中,可能同时会有成百上千个访问数据库的请求,如果Web应用程序为每一个客户请求分配一个数据库连接,将导致性能的急剧下降。为了能够重复利用数据库连接,提高对请求的响应时间和服务器的性能,可以采用连接池技术。连接池技术预先建立多个数据库连接对象,然后将连接对象保存到连接池中,当客户请求到来时,从池中取出一个连接对象为客户服务,当请求完成后,客户程序调用close()方法,将连接对象放回池中。
在普通的数据库访问程序中,客户程序得到的连接对象是物理连接,调用连接对象的close()方法将关闭连接,而采用连接池技术,客户程序得到的连接对象是连接池中物理连接的一个句柄,调用连接对象的close()方法,物理连接并没有关闭,数据源的实现只是删除了客户程序中的连接对象和池中的连接对象之间的联系。