java连接数据库jdbc
JDBC(Java数据库连接性)是Java API,用于管理与数据库的连接,发出查询和命令以及处理从数据库获得的结果集。 JDBC在1997年作为JDK 1.1的一部分发布,是为Java持久层开发的首批组件之一。
JDBC最初被认为是客户端API,它使Java客户端能够与数据源进行交互。 JDCB 2.0改变了这一点,JDCB 2.0包括一个支持服务器端JDBC连接的可选软件包。 从那时起,每个新的JDBC版本都对客户端软件包( java.sql
)和服务器端软件包( javax.sql
)进行了更新。 JDBC 4.3是撰写本文时的最新版本,已于2017年9月作为Java SE 9的一部分发布。
本文提供了JDBC的概述,然后是使用JDBC API将Java客户端与轻量级关系数据库SQLite连接的动手入门。
JDBC如何工作
JDBC作为基于C的ODBC(开放数据库连接)API的替代产品而开发,提供了编程级别的接口,该接口处理Java应用程序与数据库或RDBMS通信的机制。 JDBC接口包括两层:
- JDBC API支持Java应用程序与JDBC管理器之间的通信。
- JDBC驱动程序支持JDBC管理器和数据库驱动程序之间的通信。
JDBC是应用程序代码与之交互的通用API。 下面是您正在使用的数据库的JDBC兼容驱动程序。
图1是Java持久层中JDBC的体系结构概述。
JavaWorld / IDG
图1. Java持久层中的JDBC
使用JDBC连接数据库
Java生态系统中编程的幸运事实之一是,您可能会为所选的任何数据库找到稳定的JDBC数据库连接器。 在本教程中,我们将使用SQLite来了解JDBC,主要是因为它非常易于使用。
使用JDBC连接到数据库的步骤如下:
- 安装或找到您要访问的数据库。
- 包括JDBC库。
- 确保所需的JDBC驱动程序在类路径中。
- 使用JDBC库获得与数据库的连接。
- 使用该连接来发出SQL命令。
- 完成后关闭连接。
我们将一起完成这些步骤。
查找JDBC驱动程序
要找到要使用的数据库的驱动程序,只需对数据库和JDBC进行网络搜索。 例如,键入“ mysql jdbc driver
”将打开MySQL驱动程序。 我挑战您寻找没有JDBC驱动程序的Java兼容数据库!
步骤1.下载并安装SQLite
SQLite是一个非常紧凑的数据库。 它不是供生产使用的,而是快速尝试的绝佳选择。 SQLite使用文件作为其功能数据库,而无需安装任何服务或守护程序。
要开始进行此演示,请继续下载SQLite示例数据库 。 解压缩.db
文件并将其保存在您不会忘记的地方。
该文件包含一个基于功能文件的数据库以及我们可以使用的示例架构和数据。
SQL和JDBC
在过去的十年中,NoSQL变得越来越流行,但是关系数据库仍然是使用中最常见的数据存储类型。 关系数据库是一个结构化的存储库,由具有列和行的表组成。 SQL(结构化查询语言)是数据架构师用来在关系数据库中创建,读取,更新和删除新记录之类的语言。 JDBC是从Java到SQL的适配器层 :它为Java开发人员提供了一个公共接口,用于连接数据库,发出查询和命令以及管理响应。
步骤2.将JDBC导入Java应用程序
我们可以在IDE中进行编码,但是直接在文本编辑器中进行编码将更好地展示JDBC的简单性。 首先,您需要为您的操作系统安装兼容的JDK 。
假设您已经安装了Java平台开发人员工具,那么我们可以从创建一个简单的Java程序开始。 在文本编辑器中,粘贴清单1中所示的代码。将此文件WhatIsJdbc.java
。
清单1.一个简单的Java程序
class WhatIsJdbc{
public static void main(String args[]){
System.out.println("Hello JavaWorld");
}
}
class WhatIsJdbc{
public static void main(String args[]){
System.out.println("Hello JavaWorld");
}
}
现在,通过输入以下命令来编译代码: javac WhatIsJdbc.java
。 编译将输出WhatIsJdbc.class
文件。 从命令行使用以下代码执行该文件: java WhatIsJdbc
。
(有关在命令行上与JDK交互的更多信息,请参见“ 什么是JDK?Java开发者工具包简介 ”。)
一旦有了基本的Java程序,就可以包括JDBC库。 将清单2中的代码粘贴到简单Java程序的开头。
清单2. JDBC导入
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
这些导入中的每一个都提供对促进标准Java数据库连接的类的访问:
-
Connection
表示与数据库的连接。 -
DriverManager
获取与数据库的连接。 (另一个选项是DataSource
,用于连接池。) -
SQLException
处理Java应用程序和数据库之间SQL错误。 -
ResultSet
和Statement
对数据结果集和SQL语句进行建模。
我们将很快看到其中的每一个。
步骤3.将JDBC驱动程序添加到您的类路径中
接下来,将SQLite驱动程序添加到类路径中。 JDBC驱动程序是为特定数据库实现JDBC API的类。
从GitHub 下载SQLite驱动程序 。 确保获取最新的.jar
文件并将其存储在您会记得的地方。
下次执行Java程序时,将通过类路径将.jar
文件拉入。 有几种设置类路径的方法。 清单3显示了如何使用命令行开关来做到这一点。
清单3.在Java类路径上执行SQLite驱动程序
java.exe -classpath /path-to-driver/sqlite-jdbc-3.23.1.jar:. WhatIsJdbc
java.exe -classpath /path-to-driver/sqlite-jdbc-3.23.1.jar:. WhatIsJdbc
注意,我们将类路径设置为指向驱动程序和本地目录。 这样,Java仍会找到我们的类文件。
步骤4.获得数据库连接
现在,类路径可以访问驱动程序。 现在,将您的简单Java应用程序文件更改为清单4中的程序。
清单4.使用JDBC Connection类连接到SQLite
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
class WhatIsJdbc{
public static void main(String[] args) {
Connection conn = null;
try {
String url = "jdbc:sqlite:path-to-db/chinook/chinook.db";
conn = DriverManager.getConnection(url);
System.out.println("Got it!");
} catch (SQLException e) {
throw new Error("Problem", e);
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
class WhatIsJdbc{
public static void main(String[] args) {
Connection conn = null;
try {
String url = "jdbc:sqlite:path-to-db/chinook/chinook.db";
conn = DriverManager.getConnection(url);
System.out.println("Got it!");
} catch (SQLException e) {
throw new Error("Problem", e);
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
}
编译并执行此代码。 假设一切顺利,您将得到一个肯定的消息。
找不到合适的驱动程序?
如果收到的错误看起来像“ No suitable driver found for jdbc:sqlite
”,那么您需要重新访问类路径并确保它指向您下载的驱动程序。 驱动程序连接失败是使用JDBC的初学者最常见的绊脚石。 不要流汗。 修复它。
现在,我们可以使用一些SQL命令了。
步骤5.查询数据库
有了实时连接对象,我们可以做一些有用的事情,例如查询数据库。 清单5显示了如何使用JDBC Connection
和Statement
对象查询SQLite。
清单5.使用JDBC查询数据库
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
class WhatIsJdbc{
public static void main(String[] args) {
Connection conn = null;
try {
String url = "jdbc:sqlite:path-to-db-file/chinook/chinook.db";
conn = DriverManager.getConnection(url);
Statement stmt = null;
String query = "select * from albums";
try {
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String name = rs.getString("title");
System.out.println(name);
}
} catch (SQLException e ) {
throw new Error("Problem", e);
} finally {
if (stmt != null) { stmt.close(); }
}
} catch (SQLException e) {
throw new Error("Problem", e);
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
class WhatIsJdbc{
public static void main(String[] args) {
Connection conn = null;
try {
String url = "jdbc:sqlite:path-to-db-file/chinook/chinook.db";
conn = DriverManager.getConnection(url);
Statement stmt = null;
String query = "select * from albums";
try {
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String name = rs.getString("title");
System.out.println(name);
}
} catch (SQLException e ) {
throw new Error("Problem", e);
} finally {
if (stmt != null) { stmt.close(); }
}
} catch (SQLException e) {
throw new Error("Problem", e);
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
}
在清单5中,我们使用Connection
对象获得一个Statement
对象: conn.createStatement()
。 然后,我们使用此对象执行SQL查询: stmt.executeQuery(query)
。
executeQuery
命令返回一个ResultSet
对象,然后将其用于使用while (rs.next())
遍历数据。 在此示例中,您应该看到我们查询的专辑标题作为输出。
注意,我们还通过调用conn.close()
关闭了连接。
与JDBC的网络连接
清单5中的数据库连接字符串用于本地连接: jdbc:sqlite:path-to-db-file/chinook/chinook.db
。 要通过网络访问数据库,连接字符串将需要包括网络URL和(通常)用于访问数据库的凭据。
使用JDBC做更多的事情
到目前为止,我们已经介绍了使用JDBC连接数据库和发出SQL命令的基础知识。 虽然Statements
和ResultSet
在常见情况下可以很好地工作,但对于更大或更复杂的应用程序,您可能需要其他选项。 幸运的是,JDBC库不断发展以满足大多数数据库访问需求。
准备声明
一种提高代码灵活性的简单方法是用PreparedStatement
替换Statement
类,如清单6所示。
清单6.使用JDBC PreparedStatements
String prepState = "insert into albums values (?, ?);";
PreparedStatement prepState =
connection.prepareStatement(sql);
prepState.setString(1, "Uprising");
prepState.setString(2, "Bob Marley and the Wailers ");
int rowsAffected = preparedStatement.executeUpdate();
String prepState = "insert into albums values (?, ?);";
PreparedStatement prepState =
connection.prepareStatement(sql);
prepState.setString(1, "Uprising");
prepState.setString(2, "Bob Marley and the Wailers ");
int rowsAffected = preparedStatement.executeUpdate();
PreparedStatement
用问号( ?
)替换了Statement
的硬编码值。 使用PreparedStatement
优化代码的重用性: PreparedStatement
仅编译一次,然后可以与各种参数一起重用。 随着代码库的增长,您只需在语句中插入新值,而不用修改字符串对象本身。
批量更新
每当应用程序要发布多个更新时,分批进行它们可以极大地提高性能。 批处理的实质是获取多个更新并将它们收集在一起,然后一次发布所有更新。 清单7使用JDBC的批处理方法对几个PreparedStatement
进行批处理更新。
清单7.使用PreparedStatement进行批处理
prepState.setString(1, "Uprising");
prepState.setString(2, "Bob Marley and the Wailers");
preparedStatement.addBatch();
prepState.setString(1, "Wildflowers");
prepState.setString(2, "Tom Petty and the Heartbreakers");
preparedStatement.addBatch();
int[] rowsAffected = preparedStatement.executeBatch();
prepState.setString(1, "Uprising");
prepState.setString(2, "Bob Marley and the Wailers");
preparedStatement.addBatch();
prepState.setString(1, "Wildflowers");
prepState.setString(2, "Tom Petty and the Heartbreakers");
preparedStatement.addBatch();
int[] rowsAffected = preparedStatement.executeBatch();
JDBC事务
关系数据库中的事务允许将一组更新包装在完全成功或失败的交互中。 通过JDBC使用事务的基础是告诉系统关闭自动提交,然后在完成后手动告诉系统进行提交。 默认情况下,自动提交为on ,这意味着每当运行executeUpdate
或executeInsert
,都会提交该命令。
清单8显示了JDBC事务的一小部分。
清单8. JDBC事务
connection.setAutoCommit(false);
// Use executeUpdate multiple times
connection.commit();
connection.setAutoCommit(false);
// Use executeUpdate multiple times
connection.commit();
遇到connection.commit()
时,将尝试包装在其中的所有更新,如果失败,将全部回滚。
JDBC 4.3中还有许多值得探索的功能,包括将CallableStatement
用于存储过程 ,使用DataSource
对象以提高应用程序性能(尤其是通过连接池 ),以及将JDBC ResultSet转换为Java Stream 。
特定于数据库的功能
尽管每个符合JDBC的数据库都提供了相同的核心功能,以便通过SQL与数据库连接和交互,但是某些数据库的作用要比其他数据库大。 例如,Oracle DB提供了结果缓存,这不是JDBC规范所必需的。 这是一个例子:
conn.prepareStatement ("select /*+ result_cache */ * from employees where employee_id < : 1");
conn.prepareStatement ("select /*+ result_cache */ * from employees where employee_id < : 1");
该示例摘自Oracle的JDBC OCI Driver文档。
结论
JDBC是Java最古老的API之一,它为Java应用程序开发的长期需求之一提供了易于使用的解决方案。 仅了解本文演示的几个JDBC调用,即可开始使用JDBC连接几乎所有的数据库。 完成这些命令后,就可以开始探索JDBC中内置的一些更复杂的选项。
尽管JDBC足以满足更简单的应用程序的需求,但大多数开发人员最终还是会使用Java Persistence API(JPA)来开发更加正式的数据访问层。 JPA需要更多的前期工作和对应用程序体系结构的更复杂的理解,但是它为您提供了更一致,更隔离和定义明确的数据访问层。 有关为Java应用程序开发数据持久层的更多信息,请参见本文的同伴“ 什么是JPA?Java持久性API简介 ”。
java连接数据库jdbc