spring-reading./spring-transaction/spring-transaction-dataSource/README.md

190 lines
8.1 KiB
Markdown
Raw Normal View History

2024-05-28 07:22:28 +00:00
## DataSource
- [DataSource](#datasource)
- [一、基本信息](#一基本信息)
- [二、基本描述](#二基本描述)
- [三、主要功能](#三主要功能)
- [四、接口源码](#四接口源码)
- [五、最佳实践](#五最佳实践)
### 一、基本信息
✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址
** - [github](https://github.com/xuchengsheng/spring-reading)
### 二、基本描述
`DataSource` 接口是 Java
中用于管理数据库连接的标准接口,它提供了一种抽象的方法来获取数据库连接,使得应用程序能够与不同的数据库进行交互而无需修改代码,通过配置数据源的方式可以更灵活地处理连接池、事务管理以及连接的分配等问题,从而提高了应用程序的性能和可维护性。
### 三、主要功能
1. **提供数据库连接**
+ 定义了获取数据库连接的方法,通过调用这些方法可以获取与数据库的连接,从而进行数据库操作。
2. **连接池管理**
+ 实现连接池,避免了频繁地创建和销毁数据库连接,提高了应用程序的性能。
3. **连接配置**
+ 允许配置连接的相关属性,如数据库地址、用户名、密码等信息,这些配置可以在不同的环境中灵活地进行调整。
4. **资源管理**
+ 负责管理数据库连接资源,包括连接的分配、回收、超时控制等,确保连接的有效性和可用性。
5. **实现数据源的透明性**
+ 应用程序通过 `DataSource` 获取数据库连接,无需关心具体的数据库类型和配置细节,使得代码更具可移植性和扩展性。
### 四、接口源码
`DataSource`用于获取与物理数据源的连接。`DataSource` 提供了两个获取连接的方法:`getConnection()`
`getConnection(String username, String password)`
,分别用于获取默认用户和密码的连接以及指定用户和密码的连接。此外,接口还定义了一些管理连接的方法,如获取和设置日志写入器、设置登录超时时间等。接口说明了 `DataSource`
的作用及其实现的方式,以及与 `DriverManager` 的比较。最后,该接口还提供了一个默认方法 `createConnectionBuilder()`
,用于创建连接构建器的实例。
```java
/**
* <p>此 {@code DataSource} 对象表示对物理数据源的连接工厂。作为 {@code DriverManager} 设施的替代,{@code DataSource} 对象是获取连接的首选方式。实现 {@code DataSource} 接口的对象通常会在基于 Java&trade; Naming and Directory (JNDI) API 的命名服务中注册。</p>
* <p>{@code DataSource} 接口由驱动程序供应商实现。有三种类型的实现:</p>
* <ol>
* <li>基本实现 -- 生成标准的 {@code Connection} 对象</li>
* <li>连接池实现 -- 生成自动参与连接池的 {@code Connection} 对象。该实现与中间层连接池管理器配合使用。</li>
* <li>分布式事务实现 -- 生成可用于分布式事务的 {@code Connection} 对象,几乎总是参与连接池。该实现与中间层事务管理器以及几乎总是与连接池管理器一起使用。</li>
* </ol>
* <p>{@code DataSource} 对象具有在必要时可以修改的属性。例如,如果数据源移动到不同的服务器,则可以更改服务器的属性。好处在于,因为数据源的属性可以更改,因此访问该数据源的任何代码都不需要更改。</p>
* <p>通过 {@code DataSource} 对象访问的驱动程序不会向 {@code DriverManager} 注册自己。相反,通过查找操作检索 {@code DataSource} 对象,然后用于创建 {@code Connection} 对象。对于基本实现,通过 {@code DataSource} 对象获取的连接与通过 {@code DriverManager} 设施获取的连接相同。</p>
* <p>{@code DataSource} 的实现必须包括一个公共的无参数构造函数。</p>
*
* @since 1.4
*/
public interface DataSource extends CommonDataSource, Wrapper {
/**
* <p>尝试与此 {@code DataSource} 对象表示的数据源建立连接。</p>
*
* @return 与数据源的连接
* @exception SQLException 如果发生数据库访问错误
* @throws java.sql.SQLTimeoutException 当驱动程序确定 {@code setLoginTimeout} 方法指定的超时值已超过并且至少尝试取消当前数据库连接尝试时
*/
Connection getConnection() throws SQLException;
/**
* <p>尝试使用指定用户和密码与此 {@code DataSource} 对象表示的数据源建立连接。</p>
*
* @param username 连接所代表用户的数据库用户
* @param password 用户的密码
* @return 与数据源的连接
* @exception SQLException 如果发生数据库访问错误
* @throws java.sql.SQLTimeoutException 当驱动程序确定 {@code setLoginTimeout} 方法指定的超时值已超过并且至少尝试取消当前数据库连接尝试时
* @since 1.4
*/
Connection getConnection(String username, String password) throws SQLException;
/**
* {@inheritDoc}
* @since 1.4
*/
@Override
java.io.PrintWriter getLogWriter() throws SQLException;
/**
* {@inheritDoc}
* @since 1.4
*/
@Override
void setLogWriter(java.io.PrintWriter out) throws SQLException;
/**
* {@inheritDoc}
* @since 1.4
*/
@Override
void setLoginTimeout(int seconds) throws SQLException;
/**
* {@inheritDoc}
* @since 1.4
*/
@Override
int getLoginTimeout() throws SQLException;
// JDBC 4.3
/**
* 创建一个新的 {@code ConnectionBuilder} 实例
* @implSpec 默认实现将抛出 {@code SQLFeatureNotSupportedException}
* @return 创建的 ConnectionBuilder 实例
* @throws SQLException 如果创建构建器时发生错误
* @throws SQLFeatureNotSupportedException 如果驱动程序不支持分片
* @since 9
* @see ConnectionBuilder
*/
default ConnectionBuilder createConnectionBuilder() throws SQLException {
throw new SQLFeatureNotSupportedException("createConnectionBuilder not implemented");
};
}
```
### 五、最佳实践
使用 `DataSource` 来建立与数据库的连接,体现了高内聚的设计原则,有利于后续更改数据库。通过 `MysqlDataSource` 类设置数据库连接的
URL、用户名和密码然后获取数据库连接。接着执行 SQL 查询语句将查询结果输出到控制台。最后关闭结果集、PreparedStatement
和数据库连接,释放资源。
```java
public class DataSourceDemo {
public static void main(String[] args) throws Exception {
// 使用 DataSource 体现了高内聚,有利于后面更改数据库
MysqlDataSource dataSource = new MysqlDataSource();
// 数据库连接 URL格式为 jdbc:数据库驱动名称://主机地址:端口号/数据库名称
dataSource.setUrl("jdbc:mysql://localhost:3306/spring-reading");
// 数据库用户名
dataSource.setUser("root");
// 数据库密码
dataSource.setPassword("123456");
// 建立数据库连接
Connection connection = dataSource.getConnection();
// SQL 查询语句
String sql = "SELECT * FROM scores";
// 创建 PreparedStatement 对象,用于执行 SQL 查询
PreparedStatement statement = connection.prepareStatement(sql);
// 执行查询,获取结果集
ResultSet resultSet = statement.executeQuery();
// 遍历结果集
while (resultSet.next()) {
// 获取 id 列的值
int id = resultSet.getInt("id");
// 获取 score 列的值
String score = resultSet.getString("score");
// 输出结果
System.out.println("id: " + id + ", score: " + score);
}
// 关闭结果集、PreparedStatement 和数据库连接
resultSet.close();
statement.close();
connection.close();
}
}
```
运行结果,从 "spring-reading" 的数据库的 "scores" 表中检索到的数据。每行都包括一个 "id" 和一个 "score" 列。
```java
id: 1, score: 3.50
id: 2, score: 3.65
id: 3, score: 4.00
id: 4, score: 3.85
id: 5, score: 4.00
id: 6, score: 3.65
```