在上一篇文章Java JDBC Steps to Connect to DB中给出的示例中,我们已经了解了如何使用DriverManager类获取连接。这对于您只需要使用连接进行测试并关闭它的示例代码是可以的。但是在现实生活中的应用程序中,每次需要数据库交互时创建连接对象将非常耗时。您需要的是一个连接池,其中一开始就创建了给定数量的连接对象并被重用。
在这篇文章中,我们将看到另一种使用提供连接池的 DataSource 对象从 Java 应用程序连接到 DB 的方法。在 JDBC 中使用 DataSource 还有其他优点。
使用数据源的优势
- 抽象层——在企业应用程序中,您可以在应用程序服务器中配置 JDBC 数据源并将其注册到 JNDI。这样,用户只需要知道 DataSource 的绑定逻辑名称,并且隐藏了 DB 特定的详细信息。
- 连接池- 如果池中有一个可以满足请求的连接,它会将连接返回给应用程序。如果池中的所有连接都在使用中,则会创建一个新连接并将其返回给应用程序。应用程序使用连接在数据库上执行一些工作,然后将对象返回到池中。然后该连接可用于下一个连接请求。
通过将连接池化,您可以重用连接对象,而不是每次都创建它,从而提高数据库密集型应用程序的性能,因为创建连接对象在时间和资源方面都是昂贵的。
- 分布式事务——DataSource 实现还可以提供可用于分布式事务的连接对象。分布式事务是访问两个或多个 DBMS 服务器的事务。
Java中的数据源接口
JDBC API 提供了一个接口DataSource,该接口必须由供应商特定的 DataSource 实现来实现。DataSource 接口是javax.sql 包的一部分,它有两个被覆盖的方法。
- 获取连接()
- getConnection(字符串用户名,字符串密码)
这两种方法都返回一个Connection对象。
数据源实现
一个 JDBC 驱动程序应该至少包含一个基本的 DataSource 实现。例如 MySQL DB JDBC 驱动程序包括实现com.mysql.jdbc.jdbc2.optional.MysqlDataSource和 Oracle DB 的实现是 oracle.jdbc.pool.OracleDataSource。
JDBC 数据源示例
让我们看一些使用中的 DataSource 示例。首先让我们看一个 MySQL 数据源的例子。尽管人们更喜欢将连接池库之一Apache DBCP或mchange c3p0至少与独立的 Java 程序一起使用,但我们也会看到这些示例。
MySQL 数据源示例
这里我们有一个 DataSource 类,它是一个提供 MysqlDataSource 实例的单例类。MySQL 中的模式也是netjs,表是Employee。您的类路径中应该有mysql-connector jar。
还有另一个类 DSConnection,我们在其中获取 MysqlDataSource 的实例并使用它来获取 Connection 对象。
然后使用 Select SQL 语句创建PreparedStatement对象,以获取具有传递 ID 的 Employee 数据。
DataSource.java
import com.mysql.cj.jdbc.MysqlDataSource;
public class DataSource {
private static final String DRIVER_CLASS = "com.mysql.cj.jdbc.Driver";
private static final String DB_CONNECTION_URL = "jdbc:mysql://localhost:3306/testdb";
private static final String DB_USER = "root";
private static final String DB_PWD = "root";
private static DataSource ds;
private MysqlDataSource mySqlDS = new MysqlDataSource();
//private constructor
private DataSource() {
//mySqlDS.setDriverClassName(DRIVER_CLASS);
mySqlDS.setUrl(DB_CONNECTION_URL);
mySqlDS.setUser(DB_USER);
mySqlDS.setPassword(DB_PWD);
}
/**
* static method for getting instance.
*/
public static DataSource getInstance() {
if (ds == null) {
ds = new DataSource();
}
return ds;
}
public MysqlDataSource getMySqlDS() {
return mySqlDS;
}
public void setMySqlDS(MysqlDataSource mySqlDS) {
this.mySqlDS = mySqlDS;
}
}
DSConnection.java
import com.mysql.cj.jdbc.MysqlDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DSConnection {
public static void main(String[] args) {
DSConnection dsCon = new DSConnection();
try {
dsCon.displayEmployee(1);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param connection
* @param id
* @throws SQLException
*/
private void displayEmployee(int id) throws SQLException {
Connection connection = null;
String selectSQL = "Select * from employee where id = ?";
PreparedStatement prepStmt = null;
try {
MysqlDataSource basicDS = DataSource.getInstance().getMySqlDS();
connection = basicDS.getConnection();
prepStmt = connection.prepareStatement(selectSQL);
prepStmt.setInt(1, id);
ResultSet rs = prepStmt.executeQuery();
while (rs.next()) {
System.out.println("id : " + rs.getInt("id") + " Name : "
+ rs.getString("name") + " Age : " + rs.getInt("age"));
}
} finally {
if (prepStmt != null) {
prepStmt.close();
}
if (connection != null) {
connection.close();
}
}
}
}
使用 Apache DBCP 的数据源示例
对于需要数据源的独立 Java 程序,使用 DBCP 等连接池库会更方便。
您需要项目的类路径中的以下 jars(下载路径- DBCP – Overview),根据您的 Java 和 DB 版本检查版本。
commons-dbcp2-2.1.1.jar commons-pool2-2.5.0.jar commons-logging-1.2.jar
以及所用数据库的 JDBC 驱动程序。在此示例中使用 MySQL,因此使用 mysql-connector-java-5.1.39 jar。
这里我们有一个 DataSource 类,它是一个创建并返回 dbcp2 BasicDataSource 实例的单例类。
还有另一个类 DSConnection,我们在其中获取 dbcp2 BasicDataSource 的实例并使用它来获取 Connection 对象。
然后使用 Select SQL 语句创建 PreparedStatement 对象,以获取具有传递 ID 的 Employee 数据。
MySQL 中的数据库模式是 netjs,表是 Employee。
DataSource.java
package DBCP;
import org.apache.commons.dbcp2.BasicDataSource;
public class DataSource {
private static final String DRIVER_CLASS = "com.mysql.cj.jdbc.Driver";
private static final String DB_CONNECTION_URL = "jdbc:mysql://localhost:3306/testdb";
private static final String DB_USER = "root";
private static final String DB_PWD = "root";
private static DataSource ds;
private BasicDataSource basicDS = new BasicDataSource();
//private constructor
private DataSource() {
//BasicDataSource basicDS = new BasicDataSource();
basicDS.setDriverClassName(DRIVER_CLASS);
basicDS.setUrl(DB_CONNECTION_URL);
basicDS.setUsername(DB_USER);
basicDS.setPassword(DB_PWD);
// Parameters for connection pooling
basicDS.setInitialSize(10);
basicDS.setMaxTotal(10);
}
/**
* static method for getting instance.
*/
public static DataSource getInstance() {
if (ds == null) {
ds = new DataSource();
}
return ds;
}
public BasicDataSource getBasicDS() {
return basicDS;
}
public void setBasicDS(BasicDataSource basicDS) {
this.basicDS = basicDS;
}
}
DSConnection.java
package DBCP;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.dbcp2.BasicDataSource;
public class DSConnection {
public static void main(String[] args) {
DSConnection dsCon = new DSConnection();
try {
dsCon.displayEmployee(1);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param connection
* @param id
* @throws SQLException
*/
private void displayEmployee(int id) throws SQLException {
Connection connection = null;
String selectSQL = "Select * from employee where id = ?";
PreparedStatement prepStmt = null;
try {
BasicDataSource basicDS = DataSource.getInstance().getBasicDS();
connection = basicDS.getConnection();
prepStmt = connection.prepareStatement(selectSQL);
prepStmt.setInt(1, id);
ResultSet rs = prepStmt.executeQuery();
while (rs.next()) {
System.out.println("id : " + rs.getInt("id") + " Name : "
+ rs.getString("name") + " Age : " + rs.getInt("age"));
}
} finally {
if (prepStmt != null) {
prepStmt.close();
}
if (connection != null) {
connection.close();
}
}
}
}
使用 c3p0 的数据源示例
获取 DataSource 对象的另一种方法是使用 c3p0 库。使用独立的 Java 程序,您可以创建ComboPooledDataSource的实例。
使用的罐子
c3p0-0.9.5.2.jar 更改-commons-java-0.2.11.jar
如果我们保留与上述相同的类结构。现在课程看起来像 -
DataSource.java
package c3p0;
import java.beans.PropertyVetoException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSource {
private static final String DRIVER_CLASS = "com.mysql.cj.jdbc.Driver";
private static final String DB_CONNECTION_URL = "jdbc:mysql://localhost:3306/testdb";
private static final String DB_USER = "root";
private static final String DB_PWD = "root";
private static DataSource ds;
private ComboPooledDataSource cpds = new ComboPooledDataSource();
//private constructor
private DataSource() throws PropertyVetoException {
cpds.setDriverClass(DRIVER_CLASS); //loads the jdbc driver
cpds.setJdbcUrl(DB_CONNECTION_URL);
cpds.setUser(DB_USER);
cpds.setPassword(DB_PWD);
// the settings below are optional
// c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
}
/**
* Static method for getting instance.
*
* @throws PropertyVetoException
*/
public static DataSource getInstance() throws PropertyVetoException {
if (ds == null) {
ds = new DataSource();
}
return ds;
}
public ComboPooledDataSource getCpds() {
return cpds;
}
public void setCpds(ComboPooledDataSource cpds) {
this.cpds = cpds;
}
}
DSConnection.java
package c3p0;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DSConnection {
public static void main(String[] args) throws PropertyVetoException {
DSConnection dsCon = new DSConnection();
try {
dsCon.displayEmployee(1);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param connection
* @param id
* @throws SQLException
* @throws PropertyVetoException
*/
private void displayEmployee(int id) throws SQLException, PropertyVetoException {
Connection connection = null;
String selectSQL = "Select * from employee where id = ?";
PreparedStatement prepStmt = null;
try {
ComboPooledDataSource basicDS = DataSource.getInstance().getCpds();
connection = basicDS.getConnection();
prepStmt = connection.prepareStatement(selectSQL);
prepStmt.setInt(1, id);
ResultSet rs = prepStmt.executeQuery();
while (rs.next()) {
System.out.println("id : " + rs.getInt("id") + " Name : "
+ rs.getString("name") + " Age : " + rs.getInt("age"));
}
for (int i = 1; i <= 1000; i++) {
Connection conn = basicDS.getConnection();
System.out.println(conn + " : " + i);
System.out.println("正在使用连接数:" + basicDS.getNumBusyConnections());
System.out.println("空闲连接数:" + basicDS.getNumIdleConnections());
System.out.println("总连接数:" + basicDS.getNumConnections());
conn.close();
}
} finally {
if (prepStmt != null) {
prepStmt.close();
}
if (connection != null) {
connection.close();
}
}
}
}
这就是本主题DataSource in Java-JDBC的全部内容。如果您有任何疑问或任何建议,请发表评论。谢谢!