在本文中,我们提供了全面的JDBC教程(Java数据库连接性),这是Oracle提供的一种API,允许程序员处理Java应用程序中的不同数据库:它允许开发人员建立与数据库的连接,定义特定的客户端如何访问给定的客户端。数据库,提供了用于读取,插入,更新和删除数据库中数据条目的机制,并负责处理由不同SQL语句组成的事务。

在本文中,我们将解释主要的JDBC组件,例如语句,结果集或存储过程。

JDBC需要程序员可能要使用的不同数据库的驱动程序。

我们将对此进行详细说明,并提供一些示例。

JDBC从一开始就与Java一起出现。 1997年2月,第一个发行版随JDK 1.1一起发布,此后,JDBC一直是Java的重要组成部分。 包含JDBC的主要软件包是http://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html和http://docs.oracle.com/javase/8/ docs / api / javax / sql / package-summary.html 。

有关最新的JDBC版本(4.2)及其开发和维护的所有信息可以在JSR 221中找到。

本文中显示的所有示例都是使用Java 8更新0_25和Eclipse SDK版本Luna 4.4实现的。 在本文末尾,您可以下载所有这些示例以及更多示例!

目录

1.组成 2.连接 3.数据类型 4.驱动程序 5.数据库 6.结果集 7.存储过程 8.陈述 9.批处理命令 10.交易 11. CRUD命令 12. Java 8 13.基于JDBC构建的Sql库 14.单元测试 15.总结 16.下载 17.链接

1.组成

JDBC API允许程序员和Java应用程序与数据库进行交互。 它支持执行不同的SQL语句并处理来自不同数据源的结果。

在本节中,我们将尝试总结并列出每个Java应用程序中最重要的JDBC组件,所有这些组件将在下一章中进行详细说明。

  • 首先,Java应用程序需要创建和建立特定数据库的连接。 使用驱动程序管理器(例如,接口java.sql.DriverManager一个实例)或直接通过JDBC数据源完成此操作。 为此,可以使用接口javax.sql.DataSource 。 如前所述,我们将在下一章中更详细地解释这些组件。
  • 连接到数据库后,就可以使用java.sql.Connection执行CRUD(创建,读取,更新,删除)SQL语句或操作。 这些说明将在本教程中进行解释。
  • 为了执行这些操作,程序员可以使用基于java.sql.Statementjava.sql.PreparedStatement的类。 最后几次在多次执行同一条语句时效率更高,并提供了我们将在本教程中列出的其他好处。
    JDBC接口连接提供了创建语句实例的机制:
PreparedStatement countriesStatement = connection.prepareStatement("UPDATE COUNTRIES SET NAME = ? WHERE ID = ?");
countriesStatement.setString(1, "Spain");
countriesStatement.setInt(2, 123456789);
  • 诸如插入,更新或删除之类的操作将返回修改后的行数,而不会返回其他任何内容:
// countriesStatement belongs to the class Statement, returning number of updated rows
int n = countriesStatement.executeUpdate();
  • 选择操作(查询)以java.sql.ResultSet内部的行java.sql.ResultSet返回结果。 按名称或数字检索行; 结果元数据也可用:
// countriesStatement belongs to the class Statement
ResultSet rs = countriesStatement.executeQuery("SELECT NAME, POPULATION FROM COUNTRIES");
//rs contains the results in rows plus some metadata
...
  • 通常,JDBC使用连接池来管理连接。 连接池(例如C3P0或DBCP)有不同的实现。 这些是JDBC连接组,在需要时从应用程序使用或借用它们,并在任务完成时释放。 关于如何在JDBC中使用和配置连接池的文档很多,可以在以下链接中找到很好的教程: http://docs.oracle.com/cd/E13222_01/wls/docs81/ConsoleHelp/jdbc_connection_pools.html 。
  • 使用JDBC时,还可以使用其他功能:存储过程,可调用语句,批处理…所有这些都将在本教程中进行描述。

2.连接

为了连接到数据库,我们需要使用java.sql.Connection对象。 我们可以使用java.sql.DriverManager类的getConnection()方法来完成此操作。 此方法接收数据库主机和凭据作为参数。

此代码段显示了如何为本地MySQL数据库创建连接。

//MySQL driver is loaded
Class.forName( "com.mysql.jdbc.Driver" );
//Connection object is created using the db host and credentials
Connection connect = DriverManager.getConnection("jdbc:mysql://localhost/countries?"+ "user=root&password=root" );

连接对象允许程序员执行以下操作:

  • JDBC语句的创建:使用连接对象可以创建提供提供执行不同SQL语句方法的StatementPreparedStatementCallableStatement实例。 这是创建PreparedStatement的示例:
//the connection conn is used to create a prepared statement with the given sql operation
PreparedStatement updateStmt = conn.prepareStatement( sql );

该语句可以执行作为参数传递的sql更新。

  • 提供提交或回滚给定事务的可能性。 JDBC连接支持两种不同的工作方式: autocommit=trueautocommit=false 。 第一个将所有事务直接提交到数据库,第二个需要特殊命令才能提交或回滚事务。 我们将在本教程的相关章节中看到更多详细信息。 以下代码展示了如何更改JDBC连接的自动提交模式:
//it changes the mode to auto commit=false
connect.setAutoCommit( false );
  • 可能获取有关已使用数据库的元信息。
  • 其他选项,例如批处理,存储过程等。

我们将详细解释所有这些功能,目前最好知道什么是JDBC连接以及使用JDBC连接可以完成的操作。

3.数据类型

JDBC将Java数据类型转换为适当的JDBC类型,然后再在数据库中使用它们。 Java和JDBC数据类型之间存在默认映射,该映射提供了数据库实现和驱动程序之间的一致性。

下表包含这些映射:

的SQL JDBC / Java 二传手 吸气剂
VARCHAR java.lang.String setString getString
焦炭 java.lang.String setString getString
LONGVARCHAR java.lang.String setString getString
比特 布尔值 setBoolean getBoolean
数字 大十进制 setBigDecimal getBigDecimal
天音 字节 setByte getByte
SMALLINT setShort getShort
整数 整型 setInt getInt
比金特 setLong getLong
真实 浮动 setFloat getFloat
浮动 浮动 setFloat getFloat
setDouble getDouble
VARBINARY 字节[] setBytes getBytes
二进制 字节[] setBytes getBytes
日期 java.sql.Date 设置日期 getDate
时间 java.sql.Time 设置时间 getTime
时间戳 java.sql.Timestamp setTimestamp getTimestamp
CLOB java.sql.Clob setClob getClob
BLOB java.sql.Blob setBlob getBlob
阵列 java.sql.Array setARRAY getARRAY
参考 java.sql.Ref SetRef getRef
结构 java.sql.Struct SetStruct getStruct

在SQL和Java中,空值的处理方式有所不同。 在Java中使用SQL空值进行处理时,最好遵循一些最佳做法,例如避免使用基本类型,因为它们不能为空,但可以转换为默认值,例如int为0,booleans为false等。

取而代之的是,建议对原始类型使用包装器类。 ResultSet类包含一个名为wasNull()的方法,在这些情况下非常有用。 这是一个用法示例:

Statement stmt = conn.createStatement( );
String sql = "SELECT NAME, POPULATION FROM COUNTRIES";
ResultSet rs = stmt.executeQuery(sql);int id = rs.getInt(1);
if( rs.wasNull( ) ) {id = 0;
}

4.驱动程序

JDBC驱动程序管理器java.sql.DriverManager是JDBC API最重要的元素之一。 它是处理JDBC驱动程序列表的基本服务。 它包含允许Java应用程序连接到所需JDBC驱动程序的机制和对象。 它负责管理不同类型的JDBC数据库驱动程序。 总结驱动程序管理器的主要任务是了解可用驱动程序的列表,并处理特定选定驱动程序和数据库之间的连接。

此类中最常用的方法是DriverManager.getConnetion() 。 此方法建立与数据库的连接。

这是一个用法示例:

// Create the connection with the default credentials
java.sql.Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:mydb", "SA", "" );

我们可以使用DriverManager.registerDriver().方法注册驱动程序DriverManager.registerDriver().

new org.hsqldb.jdbc.JDBCDriver();
DriverManager.registerDriver( new org.hsqldb.jdbc.JDBCDriver() );

我们还可以通过调用Class.forName()方法来加载驱动程序:

// Loading the HSQLDB JDBC driver
Class.forName( "org.hsqldb.jdbc.JDBCDriver" );...// connection to JDBC using mysql driver
Class.forName( "com.mysql.jdbc.Driver" );

主要区别在于方法registerDriver()需要驱动程序在编译时可用,加载驱动程序类不需要驱动程序在编译时可用。 在JDBC 4之后,不需要真正调用这些方法,并且应用程序不需要单独注册驱动程序也不需要加载驱动程序类。 也建议不要使用registerDriver()方法手动注册驱动程序。

DriverManager类的其他有趣方法是getDriver(String url) ,它尝试通过给定的字符串查找驱动程序,而getDrivers()返回先前已在Driver Manager中注册的所有驱动程序的枚举:

Enumeration drivers = DriverManager.getDrivers();
while( drivers.hasMoreElements() )
{Driver driver = drivers.nextElement();System.out.println( driver.getClass() );
}

5.数据库

JDBC支持大量数据库。 它通过使用不同的驱动程序来抽象其差异和工作方式。 DriverManager类负责加载正确的数据库,在加载正确的数据库之后,用于访问数据库以查询和修改数据的代码将保持(或多或少)不变。

以下是JDBC(在Oracle中正式注册)受支持的数据库的列表: http : //www.oracle.com/technetwork/java/index-136695.html 。

在本章中,我们将展示如何使用不同的数据库:MySQL和HSQLDB。 第一个是程序员众所周知的且已被广泛使用,第二个是HSQLDB,它是一个非常有用的测试数据库,具有内存功能。 我们将看到如何同时使用这两种方法,并且会发现,除了加载适当的JDBC驱动程序之外,应用程序的其余部分保持不变:

MySQL示例:

public static void main( String[] args ) throws ClassNotFoundException, SQLException{// connection to JDBC using mysql driverClass.forName( "com.mysql.jdbc.Driver" );Connection connect = DriverManager.getConnection("jdbc:mysql://localhost/countries?"+ "user=root&password=root" );selectAll( connect );// close resources, in case of exception resources are not properly cleared
...}/*** select statement and print out results in a JDBC result set* * @param conn* @throws SQLException*/private static void selectAll( java.sql.Connection conn ) throws SQLException{Statement statement = conn.createStatement();ResultSet resultSet = statement.executeQuery( "select * from COUNTRIES" );while( resultSet.next() ){String name = resultSet.getString( "NAME" );String population = resultSet.getString( "POPULATION" );System.out.println( "NAME: " + name );System.out.println( "POPULATION: " + population );}}

内存中(HSQLDB)示例:

public static void main( String[] args ) throws ClassNotFoundException, SQLException{// Loading the HSQLDB JDBC driverClass.forName( "org.hsqldb.jdbc.JDBCDriver" );// Create the connection with the default credentialsjava.sql.Connection conn = DriverManager.getConnection( "jdbc:hsqldb:mem:mydb", "SA", "" );// Create a table in memoryString countriesTableSQL = "create memory table COUNTRIES (NAME varchar(256) not null primary key, POPULATION varchar(256) not null);";// execute the statement using JDBC normal StatementsStatement st = conn.createStatement();st.execute( countriesTableSQL );// nothing is in the database because it is just in memory, non persistentselectAll( conn );// after some insertions, the select shows something different, in the next execution these// entries will not be thereinsertRows( conn );selectAll( conn );}.../*** select statement and print out results in a JDBC result set* * @param conn* @throws SQLException*/private static void selectAll( java.sql.Connection conn ) throws SQLException{Statement statement = conn.createStatement();ResultSet resultSet = statement.executeQuery( "select * from COUNTRIES" );while( resultSet.next() ){String name = resultSet.getString( "NAME" );String population = resultSet.getString( "POPULATION" );System.out.println( "NAME: " + name );System.out.println( "POPULATION: " + population );}}

正如我们在最后的程序中看到的那样, selectAll方法的代码完全相同,只是JDBC驱动程序的加载和连接创建发生了变化。 您可以想象在不同环境下工作时,它的功能多么强大。 HSQLDB版本的代码还包含负责创建内存数据库并插入一些行的代码,但这只是出于显示和清晰的目的,可以用不同的方式完成。

6.结果集

java.sql.ResultSet表示数据库表的结果集。 通常,它是创建的; 通过执行SQL查询(使用Statement或PreparedStatement的select语句)。 它包含数据行,数据存储在该行中。 这些数据可以通过索引(以1开头)或属性名称进行访问:

// creating the result setResultSet resultSet = statement.executeQuery( "select * from COUNTRIES" );// iterating through the results rowswhile( resultSet.next() ){// accessing column values by index or nameString name = resultSet.getString( "NAME" );int population = resultSet.getInt( "POPULATION" );System.out.println( "NAME: " + name );System.out.println( "POPULATION: " + population );// accessing column values by index or nameString name = resultSet.getString( 1 );int population = resultSet.getInt( 2 );System.out.println( "NAME: " + name );System.out.println( "POPULATION: " + population );}

如前所示,ResultSets包含用于获取不同Java类型的列值的getter方法。 它还包含一个指向当前数据行的光标。 最初,光标指向第一行之前。 next方法将光标移动到下一行: java.sql.ResultSet.next()

可以使用默认属性(例如只能向前移动且不可更新的光标)创建ResultSets。 如果程序员想使用其他类型的属性,则可以在创建Statement时指定,以便通过更改传递的参数来生成结果集:

/**
* indicating result sets properties that will be created from this statement: type,
* concunrrency and holdability
*/
Statement statement = conn.createStatement( ResultSet. TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT );

使用这种结果集,可以在两个方向上移动光标,并以此目的将结果集更新或插入新数据到数据库中。

7.存储过程

在本章中,我们将解释什么是存储过程以及如何在JDBC中使用它们。 对于示例,我们将使用基于MySQL的存储过程。

存储过程是作为执行逻辑单元的一部分并执行定义的任务的SQL语句集。 当封装一组要在数据库上执行的操作时,它们非常有用。

首先,我们将在MySQL数据库中创建一个过程,以下脚本将帮助我们完成此任务:

delimiter //CREATE PROCEDURE spanish (OUT population_out INT)BEGINSELECT COUNT(*) INTO population_out FROM countries;END//delimiter ;CALL simpleproc(@a);

基本上,以上脚本创建了一个名为Spanish的过程,该过程具有一个类型为int且没有输入参数的输出属性。 该过程返回数据库中所有国家的计数。

一旦创建了过程,就可以从Java应用程序中使用它。要调用存储过程,我们需要使用接口java.sql.CallableStatement特殊语句,这些语句允许程序员执行存储过程,以指示输出属性和要使用的输入参数。 在我们的简单示例中,仅配置了输出属性。 这是一个例子:

CallableStatement callableStatement = null;// the procedure should be created in the databaseString spanishProcedure = "{call spanish(?)}";// callable statement is usedcallableStatement = connect.prepareCall( spanishProcedure );// out parameters, also in parameters are possible, not in this casecallableStatement.registerOutParameter( 1, java.sql.Types.VARCHAR );// execute using the callable statement method executeUpdatecallableStatement.executeUpdate();// attributes are retrieved by indexString total = callableStatement.getString( 1 );System.out.println( "amount of spanish countries " + total );

我们将欣赏如何使用java.sql.PreparedStatement.executeUpdate()方法指示该过程的输出存储在何处以及如何执行该过程。 大多数数据库都支持存储过程,但是它们的语法和行为可能有所不同,这就是Java处理存储过程的Java应用程序可能有所不同的原因,具体取决于存储过程的数据库。

8.陈述

如本教程中已经提到的,JDBC使用接口java.sql.Statement来执行不同的SQL查询和操作,例如插入,更新或删除。 这是基本接口,包含所有基本方法,例如java.sql.Statement.executeQuery(String)java.sql.Statement.executeUpdate(String)

当程序员不需要多次执行相同的查询或不需要对查询和语句进行参数化时,建议使用此接口的实现。 通常,我们可以说该接口适合于执行DDL语句(Create,Alter,Drop)。 这些语句通常不会多次执行,并且不需要支持不同的参数。

如果程序员在重复SQL查询或参数化时需要更好的效率,则应使用java.sql.PreparedStatement 。 该接口继承了前面提到的基本语句接口,并提供了参数化。 由于此功能,此接口可更安全地防止SQL注入攻击。 这是一段代码,显示了此接口的示例:

System.out.println( "Updating rows for " + name + "..." );String sql = "UPDATE COUNTRIES SET POPULATION=? WHERE NAME=?";PreparedStatement updateStmt = conn.prepareStatement( sql );// Bind values into the parameters.
updateStmt.setInt( 1, 10000000 ); // population
updateStmt.setString( 2, name ); // name// update prepared statement using executeUpdate
int numberRows = updateStmt.executeUpdate();System.out.println( numberRows + " rows updated..." );

使用准备好的语句的另一个好处是可以通过使用setObject()方法来处理非标准对象。 这是一个例子:

PreparedStatement updateStmt2 = conn.prepareStatement( sql );// Bind values into the parameters using setObject, can be used for any kind and type of// parameter.updateStmt2.setObject( 1, 10000000 ); // populationupdateStmt2.setObject( 2, name ); // name// update prepared statement using executeUpdatenumberRows = updateStmt2.executeUpdate();System.out.println( numberRows + " rows updated..." );updateStmt2.close();

就像在与存储过程有关的章节中提到的那样,为此目的可以使用另一个接口,它称为java.sql.CallableStatement并扩展了PreparedStatement。

9.批处理命令

JDBC提供了成批执行SQL语句列表的可能性,即全部成一行。 取决于程序员使用哪种类型的语句,代码可能有所不同,但总体思路是相同的。 在下一个代码片段中,显示了如何对java.sql.Statement使用批处理:

Statement statement = null;statement = connect.createStatement();// adding batchs to the statement
statement.addBatch( "update COUNTRIES set POPULATION=9000000 where NAME='USA'" );
statement.addBatch( "update COUNTRIES set POPULATION=9000000 where NAME='GERMANY'" );
statement.addBatch( "update COUNTRIES set POPULATION=9000000 where NAME='ARGENTINA'" );// usage of the executeBatch method
int[] recordsUpdated = statement.executeBatch();int total = 0;
for( int recordUpdated : recordsUpdated )
{total += recordUpdated;
}System.out.println( "total records updated by batch " + total );

并使用java.sql.PreparedStatement

String sql = "update COUNTRIES set POPULATION=? where NAME=?";PreparedStatement preparedStatement = null;preparedStatement = connect.prepareStatement( sql );preparedStatement.setObject( 1, 1000000 );preparedStatement.setObject( 2, "SPAIN" );// adding batchespreparedStatement.addBatch();preparedStatement.setObject( 1, 1000000 );preparedStatement.setObject( 2, "USA" );// adding batchespreparedStatement.addBatch();// executing all batchsint[] updatedRecords = preparedStatement.executeBatch();int total = 0;for( int recordUpdated : updatedRecords ){total += recordUpdated;}System.out.println( "total records updated by batch " + total );

我们可以看到,这些区别基本上是使用SQL查询参数的方式以及如何构建查询的,但是在一行上执行多个语句的想法是相同的。 在第一种情况下,使用方法java.sql.Statement.executeBatch() ,在第二种情况下使用java.sql.PreparedStatement.addBatch()java.sql.Statement.executeBatch()

10.交易

JDBC支持事务,并包含实现基于事务的应用程序的方法和功能。 我们将在本章中列出最重要的那些。

  • java.sql.Connection.setAutoCommit(boolean) :此方法接收布尔值作为参数,如果为true(这是默认行为),则所有SQL语句将自动保存在数据库中。 如果为false,将不会自动保留更改,这将通过使用java.sql.Connection.commit()方法来完成。
  • java.sql.Connection.commit() 。 仅当自动提交设置为false或禁用时,才可以使用此方法。 也就是说,它仅适用于非自动提交模式。 执行此方法时,自上次提交/回滚以来的所有更改都将保留在数据库中。
  • java.sql.Connection.rollback() 。 仅当禁用自动提交时,才可以使用此方法。 它撤消或还原当前事务中完成的所有更改。

这是一个用法示例,在此示例中,我们可以看到如何使用setAutoCommit(false)方法禁用自动提交模式。 调用commit()时将commit()所有更改,并使用rollback()方法rollback()当前事务更改:

Class.forName( "com.mysql.jdbc.Driver" );
Connection connect = null;
try
{// connection to JDBC using mysql driverconnect = DriverManager.getConnection( "jdbc:mysql://localhost/countries?"+ "user=root&password=root" );connect.setAutoCommit( false );System.out.println( "Inserting row for Japan..." );String sql = "INSERT INTO COUNTRIES (NAME,POPULATION) VALUES ('JAPAN', '45000000')";PreparedStatement insertStmt = connect.prepareStatement( sql );// insert statement using executeUpdateinsertStmt.executeUpdate( sql );connect.rollback();System.out.println( "Updating row for Japan..." );// update statement using executeUpdate -> will cause an error, update will not be// executed becaues the row does not existsql = "UPDATE COUNTRIES SET POPULATION='1000000' WHERE NAME='JAPAN'";PreparedStatement updateStmt = connect.prepareStatement( sql );updateStmt.executeUpdate( sql );connect.commit();}
catch( SQLException ex )
{ex.printStackTrace();//undoes all changes in current transactionconnect.rollback();
}
finally
{connect.close();
}

11. CRUD命令

CRUD来自创建,读取,更新和删除。 JDBC支持所有这些操作和命令,在本章中,我们将展示执行所有这些操作的Java代码的不同片段:

创建语句。 可以使用JDBC创建数据库,这是创建内存数据库的示例:

// Create a table in memory
String countriesTableSQL = "create memory table COUNTRIES (NAME varchar(256) not null primary key, POPULATION varchar(256) not null);";// execute the statement using JDBC normal Statements
Statement st = conn.createStatement();
st.execute( countriesTableSQL );

插入语句。 JDBC支持插入。 程序员可以使用普通的SQL语法,并将它们传递给JDBC提供的不同的语句类,例如StatementPreparedStatementCallableStatement 。 以下是几个示例:

Statement insertStmt = conn.createStatement();String sql = "INSERT INTO COUNTRIES (NAME,POPULATION) VALUES ('SPAIN', '45Mill')";
insertStmt.executeUpdate( sql );sql = "INSERT INTO COUNTRIES (NAME,POPULATION) VALUES ('USA', '200Mill')";
insertStmt.executeUpdate( sql );sql = "INSERT INTO COUNTRIES (NAME,POPULATION) VALUES ('GERMANY', '90Mill')";
insertStmt.executeUpdate( sql );

这些语句返回插入的行数。 这同样适用于update语句,这是如何更新数据库中的一组行的示例:

System.out.println( "Updating rows for " + name + "..." );Statement updateStmt = conn.createStatement();// update statement using executeUpdateString sql = "UPDATE COUNTRIES SET POPULATION='10000000' WHERE NAME='" + name + "'";int numberRows = updateStmt.executeUpdate( sql );System.out.println( numberRows + " rows updated..." );

输出为:

Updating rows for SPAIN...
4 rows updated...

选择对帐单。 可以使用JDBC语句执行任何(几乎)种类的SQL查询。 这是一个非常简单的示例,该示例读取给定表的所有行并在标准控制台中将它们打印出来:

Statement statement = conn.createStatement();ResultSet resultSet = statement.executeQuery( "select * from COUNTRIES" );while( resultSet.next() )
{String name = resultSet.getString( "NAME" );String population = resultSet.getString( "POPULATION" );System.out.println( "NAME: " + name );System.out.println( "POPULATION: " + population );
}

其输出为(取决于数据库状态):

NAME: GERMANY
POPULATION: 90Mill
NAME: SPAIN
POPULATION: 45Mill
NAME: USA
POPULATION: 200Mill

删除语句。 最后,JDBC支持删除行以及删除表和其他SQL元素。 这是一个片段,显示删除具有特定条件的所有行(在这种情况下,名称必须为“ JAPAN”):

System.out.println( "Deleting rows for JAPAN..." );
String sql = "DELETE FROM COUNTRIES WHERE NAME='JAPAN'";
PreparedStatement deleteStmt = connect.prepareStatement( sql );// delete statement using executeUpdate
int numberRows = deleteStmt.executeUpdate( sql );System.out.println( numberRows + " rows deleted..." );

Delete语句返回受影响的行数,在这种情况下,输出将是(取决于数据库状态):

Deleting rows for JAPAN...
0 rows deleted...

这些例子都是非常简单的例子。 它们是出于学习目的而编写的,但是您可以想象,只需更改传递给executeQuery()executeUpdate()方法的参数,就可以执行更复杂的SQL查询。

12. Java 8

Java 8不包含与JDBC或JDBC框架相关的任何重大更改。 但是,在使用JDBC时,可以应用Java 8的几种功能,效果非常好。 我们将展示其中的一些。 例如,可以像过去一样以完全不同的方式执行选择查询。 这是一个没有Java 8功能的情况下的示例,它与本文中所有示例中的操作大致相同:

// we always need to write this code
System.out.println( "using Java 7" );
// connection to JDBC using mysql driver
Class.forName( "com.mysql.jdbc.Driver" );
Connection connect = DriverManager.getConnection( "jdbc:mysql://localhost/countries?"+ "user=root&password=root" );// select query
PreparedStatement statement = connect.prepareStatement( "select * from COUNTRIES" );
ResultSet resultSet = statement.executeQuery();// iterating results
while( resultSet.next() )
{// access via nameObject name = resultSet.getObject( 1 );Object population = resultSet.getObject( 2 );System.out.println( "Name: " + name );System.out.println( "Population: " + population );
}// close resources, in case of exception resources are not properly cleared
resultSet.close();
statement.close();
connect.close();

这是一个使用Lambdas的相同版本。

// select method is called and lambda expression is provided, this expression will be used
// in the handle method of the functional interface
select( connect, "select * from COUNTRIES", ( resultSet ) -> {System.out.println( resultSet.getObject( 1 ) );System.out.println( resultSet.getObject( 2 ) );
} );

上面显示的这段代码包含一个select方法调用,其中第一个参数是Connection对象,第二个参数是SQL查询,第三个参数是Lambda表达式。 此Lambda表达式接收一个参数( ResultSet实例)并打印出其前两个属性,但是使用Lambda表达式主体中的该结果集可以完成任何操作。 这是select()方法的实现:

public static void select( Connection connect, String sql, ResultSetHandler handler ) throws SQLException{PreparedStatement statement = connect.prepareStatement( sql );try (ResultSet rs = statement.executeQuery()){while( rs.next() ){handler.handle( rs );}}}

和功能接口ResultSetHandler

@FunctionalInterface
public interface ResultSetHandler
{/*** This method will be executed by the lambda expression* * @param resultSet* @throws SQLException*/public void handle( ResultSet resultSet ) throws SQLException;}

我们在这里可以看到,使用某些Java 8新功能时,代码更加清晰,而且大幅减少(或不减少)。

13.基于JDBC构建的Sql库

几个著名的Java库使用JDBC来构建它们的API。 在本节中,我们将列出其中一些:

  • HSQLDB(超SQL数据库)是一种关系数据库管理系统,可提供内存和持久性存储。 它具有JDBC驱动程序(如某些示例所示)。 它具有非持久性功能,并且几乎支持所有SQL核心功能,因此对测试非常有用。 有关更多信息,请访问http://hsqldb.org/
  • DBUnit是JUnit的扩展。 当涉及数据库时,它对于单元测试非常有用。 该框架负责测试之间的数据库状态,并在测试时抽象出几个数据库属性。 要下载源代码和更多文档,请访问http://www.dbunit.org
  • DBUtils是一个Apache Commons库,旨在简化JDBC的使用。 该库包含的一些功能包括:清理资源,减少代码数量,更轻松,自动填充结果集。 该库小巧,透明且快速,应由希望直接使用JDBC的开发人员使用。 使用此库需要Java 1.6或更高版本。 有关更多文档,请访问http://commons.apache.org/proper/commons-dbutils/
  • Spring Data还包含一个与JDBC相关的模块。 它称为Spring Data JDBC Extensions。 它提供了对JDBC最常用功能的支持。 它提供了使用Oracle数据库的特殊功能。 如果您想了解有关此库的更多信息,请访问http://projects.spring.io/spring-data-jdbc-ext/
  • JOOQ是使用JDBC的公司数据仓库中非常有趣的框架。 它从SQL数据库生成Java代码,并提供API以建立JDBC连接,查询数据并以简单的方式处理结果。 有关更多信息,请访问其git hub帐户: https : //github.com/jOOQ/jOOL 。

14.单元测试

当涉及到单元测试和数据库时,总是存在几个问题:

  • 我们使用什么环境进行测试?
  • 我们是否用真实数据进行测试?
  • 还是我们使用合成的生成数据?
  • 如果没有适当的凭据,我们如何测试数据库?

几个库可以帮助我们完成这些任务。 在本章中,我们将列出其中一些,并提供一些有用的链接,在这些链接中可以找到更多信息:

  • DBUnit:如前所述,DBUnit是一个与Junit协作的测试框架。 有关更多信息,请访问http://dbunit.org。
  • TestNG:此测试框架涵盖许多测试场景,例如单元测试,功能测试,集成测试等。它基于注释。 有关此框架的更多信息,请访问其网站: http : //testng.org/doc/index.html
  • JOOQ。 该框架提供了JDBC模拟和测试功能。 它有很好的文档记录,易于使用。 有关更多信息,请访问http://jooq.org

15.总结

JDBC(Java数据库连接性)是用于Java与大量数据库和数据源(从基于SQL的数据库到Excel电子表格)之间的数据库连接的标准API。 在本教程中,我们试图解释JDBC体系结构以及如何使用它。 我们列出了JDBC使用的主要组件,并列出了用于广泛使用的不同数据库(如MySql)的一些驱动程序。

要记住的最重要的几点是:

  • 驱动程序是使Java应用程序能够与数据库一起使用的组件。 JDBC需要每个特定数据库的驱动程序。 可以在http://www.oracle.com/technetwork/java/index-136695.html上找到JDBC可用驱动程序的列表。
  • 每次都将SQL语句直接发送到数据库服务器。 JDBC包含一种称为PreparedStatement的机制,该机制具有预定的执行路径,该机制可提高效率并更好地利用资源。
  • 结果集是用于查询中的行的表示形式。
  • 存储过程是组合在一起的一组SQL语句,可以按名称调用它们,而不必分别调用它们。
  • 事务是一组SQL语句。 当调用commit()rollback()时,事务结束。 这种分组允许不同的并行工作。
  • CRUD命令是createreadupdatedelete命令。 JDBC提供了执行这些命令的机制。

本教程包含一些与Java 8有关的与JDBC有关的新可能性的信息,例如JOOQ。 我们还提到了一些使用JDBC实现的重要库,例如Spring-Data或Apache DBUtils。

16.下载JDBC教程源代码

下载
您可以在此处下载本教程的完整源代码: jdbc_ultimate_tutorial

17.链接

除了本文中指出的所有链接和资源之外,如果您想了解有关JDBC API及其功能和机制的更多信息,可以在Oracle官方网站上找到最新的最佳信息源:

  • http://docs.oracle.com/javase/8/docs/api/javax/sql/package-summary.html
  • http://docs.oracle.com/javase/8/docs/api/javax/sql/package-summary.html

翻译自: https://www.javacodegeeks.com/2015/02/jdbc-tutorial.html

JDBC教程– ULTIMATE指南(PDF下载)相关推荐

  1. 谷歌搜索引擎优化初学者指南pdf下载

    "有哪些简单的方法可以提高我的网站在谷歌中的排名?" 对于这个问题,推荐SEO初学者阅读:谷歌搜索引擎优化初学者指南 谷歌搜索引擎优化初学者指南:涵 盖了网站管理员需要考虑优化的诸 ...

  2. jdbc pdf_JDBC教程– ULTIMATE指南(PDF下载)

    jdbc pdf 在本文中,我们提供了全面的JDBC教程(Java数据库连接性),这是Oracle提供的API,允许程序员处理Java应用程序中的不同数据库:它允许开发人员建立与数据库的连接,定义特定 ...

  3. python程序猿_python程序员指南 pdf下载

    python程序员指南 pdf是一本专为对python编程感兴趣的朋友准备的指导图书,作从最基本的基础知识到繁琐的运用,都进行的详细的解答,是你自学的最好教程了,感兴趣欢迎下载学习! python程序 ...

  4. 5W字高质量java并发系列详解教程(上)-附PDF下载

    文章目录 第一章 java.util.concurrent简介 主要的组件 Executor ExecutorService ScheduledExecutorService Future Count ...

  5. Hive编程指南.pdf下载

    好东西就是要免费共享的,尤其是知识,只有个人强大了,祖国才会强大,哈哈,有点扯了!为节省大家的时间,现将现成的资料奉上: Hive编程指南.pdf 链接:https://pan.baidu.com/s ...

  6. Hibernate教程– ULTIMATE指南(PDF下载)

    编者注:在本文中,我们提供了全面的Hibernate教程. Hibernate ORM(简称Hibernate)是一个对象关系映射框架,它有助于将面向对象的域模型转换为传统的关系数据库. Hibern ...

  7. Java Servlet教程– ULTIMATE指南(PDF下载)

    Java Servlets是一种基于Java的Web技术. Java Servlet技术为Web开发人员提供了一种简单,一致的机制,以扩展Web服务器的功能并访问现有的业务系统. 几乎可以将Servl ...

  8. Java注释教程– ULTIMATE指南(PDF下载)

    编者注:在本文中,我们提供了全面的Java注释教程. Java中的注释是一项主要功能,每个Java开发人员都应该知道如何使用它们. 我们在Java Code Geeks上提供了许多教程,例如创建自己的 ...

  9. Java 8功能教程– ULTIMATE指南(PDF下载)

    编者注:在本文中,我们提供了全面的Java 8功能教程. 自Java 8公开发布以来已经有一段时间了,所有迹象都表明这是一个非常重要的版本. 我们在Java Code Geeks处提供了大量教程,例如 ...

最新文章

  1. iis7+php_5.5,IIS7+php5.5+fastcgi
  2. sql查询 关联帖子_从零学会sql,复杂查询
  3. 【PAT乙级】1049 数列的片段和 (20 分)
  4. 时间控件_Selenium时间控件的处理
  5. 2019山东省赛B - Flipping Game ZOJ - 4114 题解
  6. windows 文件对话框
  7. Leaflet工作笔记-GIS地图上构造echarts的3D图
  8. Mac 运行goland出现can‘t load package: package xxxx is not in GOROOT问题排查
  9. 使用Java Mail接收 Gmail 电子邮件
  10. C#中的委托与事件 笔记
  11.  paip.android环境搭建与开发事例
  12. excel计算机二级考试试题,计算机二级考试Excel操作考试题.doc
  13. 树莓派Pico开发板硬件扩展接口及电源模块解析
  14. js验证开始日期不能大于结束日期_js如何判断开始时间不能大于结束时间
  15. Excel:12 个操作小技巧
  16. 【开发工具】SVN 忽略指定类型文件或指定名称文件夹
  17. [Android源码分析]L2CAP的bind分析以及psm和cid的介绍和实现
  18. 【命名规则】小驼峰?大驼峰?
  19. 硬盘串口和并口的区别
  20. EDA-什么是综合?什么是适配?

热门文章

  1. myeclipse 2016 ci3破解教程(含软件下载)
  2. MyBatis中ThreadLocal
  3. 微信小程序父级之间的传值_微信小程序自定义组件封装及父子间组件传值的方法...
  4. 图像sobel梯度详细计算过程_数字图像处理(第十章)
  5. IDEA集成maven流程图详细介绍
  6. java oca_OCA第1部分中的Java难题
  7. java实现可选形参_Java:可选的可选实现
  8. latex如何使节标题居左_为使节构建控制平面的指南第3部分-特定于域的配置API...
  9. 手游建筑美术资源_建筑商和机械手
  10. jcg q8 固件_JCG学院开设了Java设计模式课程!