标签:资源 RoCE Servle 不同类 文件 认证 运行 描述 逻辑
JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库。
JDBC API 库包含下面提到的每个任务,都是与数据库相关的常用用法。
从根本上来说,JDBC 是一种规范,它提供了一套完整的接口,允许便携式访问到底层数据库,因此可以用 Java 编写不同类型的可执行文件,例如:
所有这些不同的可执行文件就可以使用 JDBC 驱动程序来访问数据库,这样可以方便的访问数据。
JDBC 具有 ODBC 一样的性能,允许 Java 程序包含与数据库无关的代码。
JDBC API: 提供了应用程序对 JDBC 管理器的连接。
1.下载JDBC-MySQL官方驱动
2.将JDBC驱动加入到环境变量中
3.示例代码
package com.company; //第一步:导入必须的包 import java.sql.*; public class Main { //第二步:说明JDBC驱动的名称和数据库的地址 static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost:3306/test"; //第三步:说明数据库的认证账户及密码 static final String USER = "root"; static final String PASS = "123456"; public static void main(String[] args) { //第四步:注册JDBC驱动 try { Class.forName(JDBC_DRIVER); } catch (ClassNotFoundException e) { //这里会发生类没有找到的异常! e.printStackTrace(); } //第五步:获得数据库连接 try { Connection connection = DriverManager.getConnection(DB_URL,USER,PASS); //第六步:执行查询语句 Statement statement = connection.createStatement(); String sql = "SELECT * FROM crawler_article"; ResultSet rs =statement.executeQuery(sql); while (rs.next()) { String title = rs.getString("title"); String author = rs.getString("author"); System.out.println(title+":"+author); } //第七步:关闭连接资源 rs.close(); statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); //这里会发生SQL异常,因为我们提供的的账户和密码不一定能连接成功 } } }
Java数据类型与SQL数据类型的转换:
SQL | JDBC/Java | setXXX | getXXX |
---|---|---|---|
VARCHAR | java.lang.String | setString | getString |
CHAR | java.lang.String | setString | getString |
LONGVARCHAR | java.lang.String | setString | getString |
BIT | boolean | setBoolean | getBoolean |
NUMERIC | java.math.BigDecimal | setBigDecimal | getBigDecimal |
TINYINT | byte | setByte | getByte |
SMALLINT | short | setShort | getShort |
INTEGER | int | setInt | getInt |
BIGINT | long | setLong | getLong |
REAL | float | setFloat | getFloat |
FLOAT | float | setFloat | getFloat |
DOUBLE | double | setDouble | getDouble |
VARBINARY | byte[ ] | setBytes | getBytes |
BINARY | byte[ ] | setBytes | getBytes |
DATE | java.sql.Date | setDate | getDate |
TIME | java.sql.Time | setTime | getTime |
TIMESTAMP | java.sql.Timestamp | setTimestamp | getTimestamp |
CLOB | java.sql.Clob | setClob | getClob |
BLOB | java.sql.Blob | setBlob | getBlob |
ARRAY | java.sql.Array | setARRAY | getARRAY |
REF | java.sql.Ref | SetRef | getRef |
STRUCT | java.sql.Struct | SetStruct | getStruct |
SQL 语句从数据库查询中获取数据,并将数据返回到结果集中。SELECT 语句是一种标准的方法,它从一个数据库中选择行记录,并显示在一个结果集中。 java.sql.ResultSet 接口表示一个数据库查询的结果集。一个 ResultSet 对象控制一个光标指向当前行的结果集。术语“结果集”是指包含在 ResultSet 对象中的行和列的数据。
ResultSet 接口的方法可细分为三类-
光标的移动基于 ResultSet 的属性。用相应的语句生成 ResultSet 对象时,同时生成 ResultSet 的属性。
JDBC 提供了连接方法通过下列创建语句来生成你所需的 ResultSet 对象:
第一个参数表示 ResultSet 对象的类型,第二个参数是两个 ResultSet 常量之一,该常量用于判断该结果集是只读的还是可修改的。
在 ResultSet 接口中包括如下几种方法涉及移动光标-
S.N. | 方法 & 描述 |
---|---|
1 | public void beforeFirst() throws SQLException
将光标移动到第一行之前。 |
2 | public void afterLast() throws SQLException
将光标移动到最后一行之后。 |
3 | public boolean first() throws SQLException
将光标移动到第一行。 |
4 | public void last() throws SQLException
将光标移动到最后一行。 |
5 | public boolean absolute(int row) throws SQLException
将光标移动到指定的第 row 行。 |
6 | public boolean relative(int row) throws SQLException
将光标移动到当前指向的位置往前或往后第 row 行的位置。 |
7 | public boolean previous() throws SQLException
将光标移动到上一行,如果超过结果集的范围则返回 false。 |
8 | public boolean next() throws SQLException
将光标移动到下一行,如果是结果集的最后一行则返回 false。 |
9 | public int getRow() throws SQLException
返回当前光标指向的行数的值。 |
10 | public void moveToInsertRow() throws SQLException
将光标移动到结果集中指定的行,可以在数据库中插入新的一行。当前光标位置将被记住。 |
11 | public void moveToCurrentRow() throws SQLException
如果光标处于插入行,则将光标返回到当前行,其他情况下,这个方法不执行任何操作。 |
ResultSet接口中含有几十种从当前行获取数据的方法。
每个可能的数据类型都有一个 get 方法,并且每个 get 方法有两个版本-
例如,如果你想查看的列包含一个 int 类型,你需要在 ResultSet 中调用 getInt()方法-
S.N. | 方法 & 描述 |
---|---|
1 | public int getInt(String columnName) throws SQLException
返回当前行中名为 columnName 的列的 int 值。 |
2 | public int getInt(int columnIndex) throws SQLException
返回当前行中指定列的索引的 int 值。列索引从 1 开始,意味着行中的第一列是 1 ,第二列是 2 ,以此类推。 |
同样的,在 ResultSet 接口中还有获取八个 Java 原始类型的 get 方法,以及常见的类型,比如 java.lang.String,java.lang.Object 和 java.net.URL。
也有用于获取 SQL 数据类型 java.sql.Date, java.sql.Time, java.sql.Timestamp, java.sql.Clob,java.sql.Blob 中的方法。查看文档可以了解使用这些 SQL 数据类型的更多的信息。
ResultSet 接口包含了一系列的更新方法,该方法用于更新结果集中的数据。
用 get 方法可以有两个更新方法来更新任一数据类型-
例如,要更新一个结果集的当前行的 String 列,你可以使用任一如下所示的 updateString()方法-
S.N. | 方法 & 描述 |
---|---|
1 | public void updateString(int columnIndex, String s) throws SQLException
将指定列的字符串的值改为 s。 |
2 | public void updateString(String columnName, String s) throws SQLException
类似于前面的方法,不同之处在于指定的列是用名字来指定的,而不是它的索引。 |
八个原始数据类型都有其更新方法,比如 String,Object,URL,和在 java.sql 包中的 SQL 数据类型。
更新结果集中的行将改变当前行的列中的 ResultSet 对象,而不是基础数据库中的数据。要更新数据库中一行的数据,你需要调用以下的任一方法-
S.N. | 方法 & 描述 |
---|---|
1 | public void updateRow()
通过更新数据库中相对应的行来更新当前行。 |
2 | public void deleteRow()
从数据库中删除当前行。 |
3 | public void refreshRow()
在结果集中刷新数据,以反映数据库中最新的数据变化。 |
4 | public void cancelRowUpdates()
取消对当前行的任何修改。 |
5 | public void insertRow()
在数据库中插入一行。本方法只有在光标指向插入行的时候才能被调用。 |
如果你的 JDBC 连接是处于自动提交模式下,该模式为默认模式,那么每句 SQL 语句都是在其完成时提交到数据库。
对简单的应用程序来说这种模式相当好,但有三个原因你可能想关闭自动提交模式,并管理你自己的事务-
你可以通过事务在任意时间来控制以及更改应用到数据库。它把单个 SQL 语句或一组 SQL 语句作为一个逻辑单元,如果其中任一语句失败,则整个事务失败。
若要启用手动事务模式来代替 JDBC 驱动程序默认使用的自动提交模式的话,使用 Connection 对象的的 setAutoCommit()方法。如果传递一个布尔值 false 到 setAutoCommit()方法,你就关闭自动提交模式。你也可以传递一个布尔值 true 将其再次打开。
例如,如果有一个名为 conn 的 Connection 对象,以下的代码将关闭自动提交模式-
conn.setAutoCommit(false);
当你完成了你的修改,并且要提交你的修改,可以在 connection 对象里调用 commit()方法,如下所示-
conn.commit( );
另外,用名为 conn 的连接回滚数据到数据库,使用如下所示的代码-
conn.rollback( );
下面的例子说明了如何使用提交和回滚对象-
try{ //Assume a valid connection object conn conn.setAutoCommit(false); Statement stmt = conn.createStatement(); String SQL = "INSERT INTO Employees " + "VALUES (106, 20, ‘Rita‘, ‘Tez‘)"; stmt.executeUpdate(SQL); //Submit a malformed SQL statement that breaks String SQL = "INSERTED IN Employees " + "VALUES (107, 22, ‘Sita‘, ‘Singh‘)"; stmt.executeUpdate(SQL); // If there is no error. conn.commit(); }catch(SQLException se){ // If there is any error. conn.rollback(); }
在这种情况下,之前的 INSERT 语句不会成功,一切都将被回滚到最初状态。
新的 JDBC 3.0 还原点接口提供了额外的事务控制。大部分现代的数据库管理系统的环境都支持设定还原点,例如 Oracle 的 PL/SQL。
当你在事务中设置一个还原点来定义一个逻辑回滚点。如果在一个还原点之后发生错误,那么可以使用 rollback 方法来撤消所有的修改或在该还原点之后所做的修改。
Connection 对象有两个新的方法来管理还原点-
setSavepoint(String savepointName): 定义了一个新的还原点。它也返回一个 Savepoint 对象。
有一个 rollback (String savepointName) 方法,该方法可以回滚到指定的还原点。
下面的例子说明了如何使用 Savepoint 对象-
try{ //Assume a valid connection object conn conn.setAutoCommit(false); Statement stmt = conn.createStatement(); //set a Savepoint Savepoint savepoint1 = conn.setSavepoint("Savepoint1"); String SQL = "INSERT INTO Employees " + "VALUES (106, 20, ‘Rita‘, ‘Tez‘)"; stmt.executeUpdate(SQL); //Submit a malformed SQL statement that breaks String SQL = "INSERTED IN Employees " + "VALUES (107, 22, ‘Sita‘, ‘Tez‘)"; stmt.executeUpdate(SQL); // If there is no error, commit the changes. conn.commit(); }catch(SQLException se){ // If there is any error. conn.rollback(savepoint1); }
在这种情况下,之前的 INSERT 语句不会成功,一切都将被回滚到最初状态。
批处理是指你将关联的 SQL 语句组合成一个批处理,并将他们当成一个调用提交给数据库。
当你一次发送多个 SQL 语句到数据库时,可以减少通信的资源消耗,从而提高了性能。
JDBC 驱动程序不一定支持该功能。你可以使用 DatabaseMetaData.supportsBatchUpdates() 方法来确定目标数据库是否支持批处理更新。如果你的JDBC驱动程序支持此功能,则该方法返回值为 true。
Statement,PreparedStatement 和 CallableStatement 的 addBatch() 方法用于添加单个语句到批处理。
executeBatch() 方法用于启动执行所有组合在一起的语句。
executeBatch() 方法返回一个整数数组,数组中的每个元素代表了各自的更新语句的更新数目。
使用 Statement 对象来使用批处理所需要的典型步骤如下所示-
示例
下面的代码段提供了一个使用 Statement 对象批量更新的例子-
// Create statement object Statement stmt = conn.createStatement(); // Set auto-commit to false conn.setAutoCommit(false); // Create SQL statement String SQL = "INSERT INTO Employees (id, first, last, age) " + "VALUES(200,‘Zia‘, ‘Ali‘, 30)"; // Add above SQL statement in the batch. stmt.addBatch(SQL); // Create one more SQL statement String SQL = "INSERT INTO Employees (id, first, last, age) " + "VALUES(201,‘Raj‘, ‘Kumar‘, 35)"; // Add above SQL statement in the batch. stmt.addBatch(SQL); // Create one more SQL statement String SQL = "UPDATE Employees SET age = 35 " + "WHERE id = 100"; // Add above SQL statement in the batch. stmt.addBatch(SQL); // Create an int[] to hold returned values int[] count = stmt.executeBatch(); //Explicitly commit statements to apply changes conn.commit();
使用 prepareStatement 对象来使用批处理需要的典型步骤如下所示-
下面的代码段提供了一个使用 PrepareStatement 对象批量更新的示例-
// Create SQL statement String SQL = "INSERT INTO Employees (id, first, last, age) " + "VALUES(?, ?, ?, ?)"; // Create PrepareStatement object PreparedStatemen pstmt = conn.prepareStatement(SQL); //Set auto-commit to false conn.setAutoCommit(false); // Set the variables pstmt.setInt( 1, 400 ); pstmt.setString( 2, "Pappu" ); pstmt.setString( 3, "Singh" ); pstmt.setInt( 4, 33 ); // Add it to the batch pstmt.addBatch(); // Set the variables pstmt.setInt( 1, 401 ); pstmt.setString( 2, "Pawan" ); pstmt.setString( 3, "Singh" ); pstmt.setInt( 4, 31 ); // Add it to the batch pstmt.addBatch(); //add more batches . . . . //Create an int[] to hold returned values int[] count = stmt.executeBatch(); //Explicitly commit statements to apply changes conn.commit();
假设,你需要执行下面的 Oracle 存储过程-
CREATE OR REPLACE PROCEDURE getEmpName (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS BEGIN SELECT first INTO EMP_FIRST FROM Employees WHERE ID = EMP_ID; END;
注意:上面的存储过程是在 Oracle 使用的,但我们使用的是 MySQL 数据库,所以我们在 MySQL 的环境下需要重新写出相同功能的代码,下面的代码是在 EMP 数据库中创建相同功能的代码-
DELIMITER $$ DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$ CREATE PROCEDURE `EMP`.`getEmpName` (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255)) BEGIN SELECT first INTO EMP_FIRST FROM Employees WHERE ID = EMP_ID; END $$ DELIMITER ;
当前有三种类型的参数:IN,OUT 和 INOUT。PreparedStatement 对象只能使用 IN 参数。CallableStatement 对象可以使用所有的三种类型。
下面是三种类型参数的定义-
参数 | 描述 |
---|---|
IN | 当 SQL 语句创建的时候,该参数的值是未知的。你可以用 setXXX() 方法将值绑定到 IN 参数里。 |
OUT | 该参数的值是由 SQL 语句的返回值。你可以用 getXXX() 方法从 OUT 参数中检索值。 |
INOUT | 该参数同时提供输入和输出值。你可以用 setXXX() 方法将值绑定到 IN 参数里,并且也可以用 getXXX() 方法从 OUT 参数中检索值。 |
下面的代码片段展示了如何使用 Connection.prepareCall() 方法实现一个基于上述存储过程的 CallableStatement 对象-
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt = conn.prepareCall (SQL); . . . } catch (SQLException e) { . . . } finally { . . . }
字符串变量 SQL 使用参数占位符来表示存储过程。
使用 CallableStatement 对象就像使用 PreparedStatement 对象。在执行该语句前,你必须将值绑定到所有的参数,否则你将收到一个 SQL 异常。
如果你有 IN 参数,只要按照适用于 PreparedStatement 对象相同的规则和技巧;用 setXXX()方法来绑定对应的 Java 数据类型。
当你使用 OUT 和 INOUT 参数就必须采用额外的 CallableStatement 方法:registerOutParameter()。registerOutParameter() 方法将 JDBC 数据类型绑定到存储过程返回的数据类型。
一旦你调用了存储过程,你可以用适当的 getXXX()方法从 OUT 参数参数中检索数值。这种方法将检索出来的 SQL 类型的值映射到 Java 数据类型。
正如你关闭其它的 Statement 对象,出于同样的原因,你也应该关闭 CallableStatement 对象。
close()方法简单的调用就可以完成这项工作。如果你先关闭了 Connection 对象,那么它也会关闭 CallableStatement 对象。然而,你应该始终明确关闭 CallableStatement 对象,以确保该对象被彻底关闭。
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt = conn.prepareCall (SQL); . . . } catch (SQLException e) { . . . } finally { cstmt.close(); }
PreparedStatement 对象必须具备使用输入和输出流来提供参数数据的能力。这使你能够将整个文件存储到数据库列中,这样数据库就能存储大型数据,例如 CLOB 和 BLOB 数据类型。
用于流数据有下列几种方法-
setXXXStream()方法需要一个额外的参数,该参数是除了参数占位符的文件大小。这个参数通知驱动程序通过使用流有多少数据被发送到数据库中。
示例
假如我们到要上传一个名为 XML_Data.xml 的 XML 文件到数据库的表中。下面是该 XML 文件的内容-
<?xml version="1.0"?> <Employee> <id>100</id> <first>Zara</first> <last>Ali</last> <Salary>10000</Salary> <Dob>18-08-1978</Dob> <Employee>
将该 XML 文件和你要运行的示例保存在相同的目录的。
这个示例将创建一个数据库表 XML_Data ,然后 XML_Data.xml 将被上传到该表中。
将下面的示例拷贝并粘帖到 JDBCExample.java 中,编译并运行它,如下所示-
// Import required packages import java.sql.*; import java.io.*; import java.util.*; public class JDBCExample { // JDBC driver name and database URL static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost/EMP"; // Database credentials static final String USER = "username"; static final String PASS = "password"; public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt = null; Statement stmt = null; ResultSet rs = null; try{ // Register JDBC driver Class.forName("com.mysql.jdbc.Driver"); // Open a connection System.out.println("Connecting to database..."); conn = DriverManager.getConnection(DB_URL,USER,PASS); //Create a Statement object and build table stmt = conn.createStatement(); createXMLTable(stmt); //Open a FileInputStream File f = new File("XML_Data.xml"); long fileLength = f.length(); FileInputStream fis = new FileInputStream(f); //Create PreparedStatement and stream data String SQL = "INSERT INTO XML_Data VALUES (?,?)"; pstmt = conn.prepareStatement(SQL); pstmt.setInt(1,100); pstmt.setAsciiStream(2,fis,(int)fileLength); pstmt.execute(); //Close input stream fis.close(); // Do a query to get the row SQL = "SELECT Data FROM XML_Data WHERE id=100"; rs = stmt.executeQuery (SQL); // Get the first row if (rs.next ()){ //Retrieve data from input stream InputStream xmlInputStream = rs.getAsciiStream (1); int c; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while (( c = xmlInputStream.read ()) != -1) bos.write(c); //Print results System.out.println(bos.toString()); } // Clean-up environment rs.close(); stmt.close(); pstmt.close(); conn.close(); }catch(SQLException se){ //Handle errors for JDBC se.printStackTrace(); }catch(Exception e){ //Handle errors for Class.forName e.printStackTrace(); }finally{ //finally block used to close resources try{ if(stmt!=null) stmt.close(); }catch(SQLException se2){ }// nothing we can do try{ if(pstmt!=null) pstmt.close(); }catch(SQLException se2){ }// nothing we can do try{ if(conn!=null) conn.close(); }catch(SQLException se){ se.printStackTrace(); }//end finally try }//end try System.out.println("Goodbye!"); }//end main public static void createXMLTable(Statement stmt) throws SQLException{ System.out.println("Creating XML_Data table..." ); //Create SQL Statement String streamingDataSql = "CREATE TABLE XML_Data " + "(id INTEGER, Data LONG)"; //Drop table first if it exists. try{ stmt.executeUpdate("DROP TABLE XML_Data"); }catch(SQLException se){ }// do nothing //Build table. stmt.executeUpdate(streamingDataSql); }//end createXMLTable }//end JDBCExample
现在,让我们用下面的命令编译上面的代码-
C:\>javac JDBCExample.java C:\>
当你运行 JDBCExample 时,它将展示下面的结果-
C:\>java JDBCExample Connecting to database... Creating XML_Data table... <?xml version="1.0"?> <Employee> <id>100</id> <first>Zara</first> <last>Ali</last> <Salary>10000</Salary> <Dob>18-08-1978</Dob> <Employee> Goodbye!
标签:资源 RoCE Servle 不同类 文件 认证 运行 描述 逻辑
原文地址:https://www.cnblogs.com/MrSaver/p/9028620.html