前言
每次连接数据库都需要配置数据源(DataSource),那它到底是啥?我们应该怎么配置,当有多个数据源的时候我们要怎么处理呢?
定义
不论从中文来看,还是从英文来看,数据源指的应该都是数据的源头,那么数据的源头是哪里?从程序的角度来说,应该是数据库吧,那么明明可以直接称呼其为数据库,为什么还要搞出一个数据源出来呢?
我们再来来看看wikipedia对DataSource下的定义:
DataSource is a name given to the connection set up to a database from a server.
也就是说,DataSource其实指的是那个连接。当然,当你获取了连接之后,自然就可以获取连接所指向的那个东西的数据了。
其实一开始就理解的有问题,谁说数据的源头只能是数据库呢?数据的源头也可以是文件呀, 也可以是别的东西呀,只不过在绝大部分的情况下数据源是数据库而已。
数据源保证了应用程序与目标数据之间交互的规范和协议,它定义了数据在哪里,用户需要提供的验证信息(如果设置了需要验证的话),同时它还封装了如何进行连接的实现,向外只需要暴露接口即可。这样,我们就不需要关注底层是如何建立连接的,只需要关注业务即可。
反应在Java代码中,数据源封装了目标源的位置信息,验证信息和建立与关闭连接的操作。它把传统中需要在代码里编写配置信息和获取连接等操作抽象出一个规范或者接口,这样不同的第三方可以自行实现该接口提供不同的策略。
这样,数据源就是对应用程序是透明的,开发者只需为应用程序配置特定的数据源即可与数据库进行连接等操作。当需要更换数据库服务器或者更换数据库种类时,只需修改配置中信息即可,无需修改程序代码。这样就完成了松耦合的操作。
总结:数据源并不是理解的数据库,而是其中的连接。它除了提供目标数据库需要的数据外,还有建立连接、关闭连接的功能。
实际中的使用
显然上面那个概念,基本只需要厘清DataSource并不仅仅是目标数据库,而且还是中间的那个连接即可,那么实际中,数据源有什么值得我们注意的点吗?
原生JDK
首先我们必然要先看看在原生JDK中,DataSource类是怎么说明的:
A factory for connections to the physical data source that this DataSource object represents. 这个接口是一个工厂,通过这个接口,可以获取到实际的物理数据源的连接。
An alternative to the DriverManager facility, a DataSource object is the preferred means of getting a connection. 通过这个接口获取连接对象是首选,但是你还可以通过DriverManager来获取连接。
An object that implements the DataSource interface will typically be registered with a naming service based on the Java™ Naming and Directory (JNDI) API. 任何一个实现了这个接口的类都会被注册到JNDI API。
The DataSource interface is implemented by a driver vendor. 这个接口的实现是由各大数据库厂商来做的。
There are three types of implementations:
- Basic implementation – produces a standard Connection object 基础实现,就是产生一个连接对象
- Connection pooling implementation – produces a Connection object that will automatically participate in connection pooling. This implementation works with a middle-tier connection pooling manager. 连接池,这种方法需要和中间层连接池管理器一起使用。
- Distributed transaction implementation – produces a Connection object that may be used for distributed transactions and almost always participates in connection pooling. This implementation works with a middle-tier transaction manager and almost always with a connection pooling manager. 分布式实现
A DataSource object has properties that can be modified when necessary. For example, if the data source is moved to a different server, the property for the server can be changed. The benefit is that because the data source’s properties can be changed, any code accessing that data source does not need to be changed. 有了DataSource,就算物理数据源发生变化,我们也可以很轻松的配置而不需要改动源代码
A driver that is accessed via a DataSource object does not register itself with the DriverManager. Rather, a DataSource object is retrieved though a lookup operation and then used to create a Connection object. With a basic implementation, the connection obtained through a DataSource object is identical to a connection obtained through the DriverManager facility. 对于基础实现来说,通过 DataSource 对象获得的连接与通过 DriverManager 获得的连接是一样的
An implementation of DataSource must include a public no-arg constructor. DataSource必须包含一个默认的构造器
方法很简单,就俩,都是用来获取连接的,只不过一个是带用户名和密码的,另外一个不带。
在最最古老的年代,我们写连接数据库的语句,其实也没有用到DataSource,而是直接使用DriverManager.getConnection来获取连接。当然通过上面的注释也可以发现,目前更加推荐使用DataSource来获取连接了。
spring
原生
spring作为一款优秀的框架,本身提供了一个叫DriverManagerDataSource的DataSource实现,这个实现就是不使用连接池的实现,所以千万不要在日常的生产环境中使用!
第三方数据源
spring之所以没有提供连接池的数据源,是因为市面上已经有很多优秀的第三方数据源了,spring再实现一个也没什么意思,不如整合市面上好用的数据源。目前比较火热的数据源有:C3P0、Druid等,它们都支持连接池。连接池是一种创建和管理一组连接对象的技术。