提到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;
    }
}

到现在,我们已经可以管理基本的数据源,以后有新的数据库连接池实现也可以不断的扩展.

Comments
Write a Comment