提到JDBC免不了提到数据源
数据源主要解决的问题是用户通过java基本api创建connection的时候,需要验证密码,请求数据库server端等等操作,每一次的数据库操作,都需要进行很多步骤,这样的代价很高,为了重复利用connection及其他资源,通过数据源来管理connection,包括创建,释放分配等操作.这样大大减少了客户端到db server的代价.
数据源的管理基本有两种,一是JNDI,另外一种就是各种开源的数据库连接池管理.
1.JNDI(Java Naming and Directory Interface):
JNDI提供了一种统一的方式,可以用在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个纪录,同时返回数据库连接建立所必须的信息。JNDI对应的具体实现是每个容器提供的,针对不同的容器,需要注意一个点,就是jndi的命名空间,具体见:http://www.nll.im/post/2012/08/12/43008.html
2.数据库连接池
常见的有DBCP、C3P0、Proxool、BoneCP等,一般一个持久层框架都会使用通用的连接池接口,然后提供不同的连接池实现,根据用户的选择调用具体的实现
这里就不再赘述JNDI获取数据源的方式,主要说说第二种方式数据源的处理.
既然要支持多种数据源,我们直接使用通用的DataSource接口即可,在始配数据源的时候,我们会提供一些标准接口不提供的方法,比如直接通过一个properties文件添加一个数据源,那么我们可以定义一个接口,这个接口中再定义我们独有的那些方法DataSourceWrapper代码如下:
public interface DataSourceWrapper {
/**
* 使用properties创建数据源.
*
* @param properties
* @return
*/
public DataSource create(Properties properties);
}
这个接口定义了我们的数据源始配方法,接下来要写各个数据源的实现,这里只实现DBCP数据源的.DBCPDataSourceWrapper代码如下:
public class DBCPDataSourceWrapper implements DataSourceWrapper {
private final static Log logger = Logs.get();
@Override
public DataSource create(Properties properties) {
try {
return BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
logger.error(
"create DBCP DataSource from properties file error [properties:{}]",
properties, e);
throw new ExceptionInInitializerError(e);
}
}
}
在DBCP中,可以直接使用BasicDataSourceFactory.createDataSource(properties)方法直接创建数据源,这里我们直接调用即可,如果其他数据源没有提供对应的方法,我们可以自行获取properties文件中的value,然后设置到数据源对应的属性上,完成数据源的初始化.
数据源的初始化按照这种方式,可以提供多种多样的方式,那么如何做到根据配置切换呢.首先在常量中定义一个map,在map中存放配置和对应实现的关系,如下:
private static final Map<String, DataSourceWrapper> dataSourceWrappers = new HashMap<String, DataSourceWrapper>();
static {
dataSourceWrappers.put("dbcp", new DBCPDataSourceWrapper());
dataSourceWrappers.put("c3p0", new C3P0DataSourceWrapper());
}
然后定义一个对外获取的方法:
public static DataSourceWrapper getDataSourceWrapper(String name) {
DataSourceWrapper dataSource = dataSourceWrappers.get(name);
if (dataSource == null) {
throw new ExceptionInInitializerError(
"get datasource wrapper error! name:" + name);
}
return dataSource;
}
然后在我们的DataSourceManager中读取配置文件,切换对应的实现:
public class DataSourceManager {
private static PropertiesParser propertiesParser = new PropertiesParser(
"system.properties");
private static DataSource defaultDataSource;
static {
// 读取配置
String dsType = propertiesParser.getStringProperty("dsType");
// 获取wrapper
DataSourceWrapper dataSourceWrapper = Constants
.getDataSourceWrapper(dsType);
// 获取数据源
defaultDataSource = dataSourceWrapper.create(propertiesParser
.getUnderlyingProperties());
}
/**
* 返回默认数据源.
*
* @return
*/
public static DataSource defaultDataSource() {
return defaultDataSource;
}
}
到现在,我们已经可以管理基本的数据源,以后有新的数据库连接池实现也可以不断的扩展.