<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 在 Derby 中使用 JDBC 進行編程 > 原文: [http://zetcode.com/db/apachederbytutorial/jdbc/](http://zetcode.com/db/apachederbytutorial/jdbc/) 在本章中,我們將創建將與 Derby 數據庫一起使用的 Java 程序。 ## JDBC JDBC 是 Java 編程語言的 API,用于定義客戶端如何訪問數據庫。 它提供了查詢和更新數據庫中數據的方法。 JDBC 面向關系數據庫。 從技術角度來看,API 是`java.sql`包中的一組類。 要將 JDBC 與特定數據庫一起使用,我們需要該數據庫的 JDBC 驅動程序。 ## 客戶端/服務器和嵌入式 Derby 應用 Derby 可以通過兩種基本方式在 Java 應用中使用:客戶端/服務器和嵌入式。 對于客戶端/服務器應用,我們使用`org.apache.derby.jdbc.ClientDriver`;對于 Derby 嵌入式應用,我們使用`org.apache.derby.jdbc.EmbeddedDriver`。 ### Maven 依賴 Derby 驅動程序有兩個 Maven 依賴項:`derby`和`derbynet`。 `derby`依賴關系用于嵌入式應用,`derbynet`依賴關系用于客戶端/服務器應用。 ```java <dependency> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <version>10.13.1.1</version> </dependency> ``` 這是包含`derby`驅動程序的 Maven 依賴項。 ```java <dependency> <groupId>org.apache.derby</groupId> <artifactId>derbyclient</artifactId> <version>10.13.1.1</version> </dependency> ``` 這是包含`derbyclient`驅動程序的 Maven 依賴項。 ### 連接字符串 客戶端/服務器和嵌入式應用的連接字符串不同。 ```java jdbc:derby://localhost:1527/dbname ``` 這是客戶端/服務器應用的連接 URL。 ```java jdbc:derby:dbname ``` 這是嵌入式應用的連接 URL。 ## 創建`CARS`表 在我們的示例中,我們使用嵌入式 Derby 數據庫。 在第一個示例中,我們將創建一個`CARS`表并在其中插入八行。 ```java $ $DERBY_HOME/bin/ij ij version 10.11 ij> CONNECT 'jdbc:derby:testdb'; ij> DROP TABLE USER12.CARS; 0 rows inserted/updated/deleted ``` 如果在運行示例之前已經創建了`CARS`表,則應該從數據庫中刪除該表。 CreateCars.java ```java package com.zetcode; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; import java.util.logging.Logger; public class CreateCars { public static void main(String[] args) { Connection con = null; Statement st = null; String url = "jdbc:derby:testdb;user=USER12"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); st = con.createStatement(); st.executeUpdate("CREATE TABLE CARS(ID INT PRIMARY KEY," + "NAME VARCHAR(30), PRICE INT)"); st.executeUpdate("INSERT INTO CARS VALUES(1, 'Audi', 52642)"); st.executeUpdate("INSERT INTO CARS VALUES(2, 'Mercedes', 57127)"); st.executeUpdate("INSERT INTO CARS VALUES(3, 'Skoda', 9000)"); st.executeUpdate("INSERT INTO CARS VALUES(4, 'Volvo', 29000)"); st.executeUpdate("INSERT INTO CARS VALUES(5, 'Bentley', 350000)"); st.executeUpdate("INSERT INTO CARS VALUES(6, 'Citroen', 21000)"); st.executeUpdate("INSERT INTO CARS VALUES(7, 'Hummer', 41400)"); st.executeUpdate("INSERT INTO CARS VALUES(8, 'Volkswagen', 21600)"); DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(CreateCars.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (st != null) { st.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(CreateCars.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 該示例以嵌入式模式連接到 Derby。 它創建一個`CARS`表,并向其中添加 8 行。 最終,它關閉了 Derby。 ```java String url = "jdbc:derby:testdb;user=USER12"; ``` 這是用于以嵌入式模式和`USER12`模式連接到`testdb`數據庫的 URL。 ```java System.setProperty("derby.system.home", "/home/janbodnar/.derby"); ``` 我們為 Derby 系統目錄設置了系統屬性。 ```java con = DriverManager.getConnection(url); ``` 創建與 Derby 數據庫的連接。 創建連接后,將啟動 Derby 數據庫。 ```java st.executeUpdate("CREATE TABLE CARS(ID INT PRIMARY KEY," + "NAME VARCHAR(30), PRICE INT)"); st.executeUpdate("INSERT INTO CARS VALUES(1, 'Audi', 52642)"); ... ``` 我們執行創建數據庫并填充一些數據的 SQL 語句。 對于`INSERT`,`UPDATE`和`DELETE`語句以及類似`CREATE TABLE`的 DDL 語句,我們使用`executeUpdate()`方法。 ```java DriverManager.getConnection("jdbc:derby:;shutdown=true"); ``` Derby 數據庫引擎已關閉。 ```java } catch (SQLException ex) { Logger lgr = Logger.getLogger(CreateCars.class.getName()); ``` 我們抓到`SQLException`。 `Logger`類用于記錄錯誤消息。 ```java if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } ``` 當 Derby 引擎關閉時,將拋出`SQLException`。 我們捕獲此異常并記錄一條信息消息。 ```java } finally { try { if (st != null) { st.close(); } if (con != null) { con.close(); } ``` 在`finally`子句中,我們釋放資源。 ```java Mar 22, 2017 12:22:15 PM com.zetcode.CreateCars main INFO: Derby shut down normally java.sql.SQLException: Derby system shutdown. ... ``` 我們編譯并運行該示例。 Derby 的關閉將以`SQLException`結尾。 這是 Derby 數據庫的功能。 ## 檢索數據 接下來,我們將展示如何從數據庫表中檢索數據。 我們從`CARS`表中獲取所有數據。 `SelectAllCars.java` ```java package com.zetcode; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; import java.util.logging.Logger; public class SelectAllCars { public static void main(String[] args) { Connection con = null; Statement st = null; ResultSet rs = null; String url = "jdbc:derby:testdb"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); st = con.createStatement(); rs = st.executeQuery("SELECT * FROM USER12.CARS"); while (rs.next()) { System.out.print(rs.getInt(1)); System.out.print(" "); System.out.print(rs.getString(2)); System.out.print(" "); System.out.println(rs.getString(3)); } DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(SelectAllCars.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (rs != null) { rs.close(); } if (st != null) { st.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(SelectAllCars.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 我們從`CARS`表中獲得所有汽車,并將它們打印到控制臺。 ```java st = con.createStatement(); rs = st.executeQuery("SELECT * FROM USER12.CARS"); ``` 我們執行一個查詢,該查詢從`CARS`表中選擇所有列。 我們使用`executeQuery()`方法。 該方法執行給定的 SQL 語句,該語句返回單個`ResultSet`對象。 `ResultSet`是 SQL 查詢返回的數據表。 還要注意,由于我們尚未在 URL 中指定用戶名,因此必須在 SQL 語句中顯式提及架構名稱。 ```java while (rs.next()) { System.out.print(rs.getInt(1)); System.out.print(" "); System.out.print(rs.getString(2)); System.out.print(" "); System.out.println(rs.getString(3)); } ``` `next()`方法將光標移至結果集的下一條記錄。 當結果集中沒有更多行時,它將返回`false`。 `getInt()`和`getString()`方法檢索此`ResultSet`對象當前行中指定列的值; Java 編程語言中的`int`和`String`。 ```java 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600 Mar 22, 2017 12:28:36 PM com.zetcode.SelectAllCars main INFO: Derby shut down normally java.sql.SQLException: Derby system shutdown. ... ``` 我們編譯并運行該示例。 我們有`testdb`數據庫的`CARS`表中的所有汽車的列表。 ## 屬性 通常的做法是將配置數據放在程序外部的單獨文件中。 我們可以更改用戶,密碼或連接字符串,而無需重新編譯程序。 它在需要大量測試,調試,保護數據等的動態環境中特別有用。 在 Java 中,`Properties`是經常用于存儲基本配置數據的類。 該類用于輕松讀取和保存鍵/值屬性。 db.properties ```java db.url=jdbc:derby:testdb;user=USER12 db.user=USER12 db.passwd=34klq* db.syshome=/home/janbodnar/.derby ``` 我們有一個`db.roperties`文件,其中有四個鍵/值對。 這些是在程序執行期間動態加載的。 該文件位于`src/main/resources`目錄中。 PropertiesExample.java ```java package com.zetcode; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; public class PropertiesExample { public static void main(String[] args) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; Properties props = new Properties(); FileInputStream in = null; try { in = new FileInputStream("src/main/resources/db.properties"); props.load(in); } catch (FileNotFoundException ex) { Logger lgr = Logger.getLogger(PropertiesExample.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); } catch (IOException ex) { Logger lgr = Logger.getLogger(PropertiesExample.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); } finally { try { if (in != null) { in.close(); } } catch (IOException ex) { Logger lgr = Logger.getLogger(PropertiesExample.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); } } String url = props.getProperty("db.url"); String user = props.getProperty("db.user"); String passwd = props.getProperty("db.passwd"); try { System.setProperty("derby.system.home", props.getProperty("db.syshome")); con = DriverManager.getConnection(url, user, passwd); pst = con.prepareStatement("SELECT * FROM CARS"); rs = pst.executeQuery(); while (rs.next()) { System.out.print(rs.getInt(1)); System.out.print(": "); System.out.println(rs.getString(2)); } DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(PropertiesExample.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (rs != null) { rs.close(); } if (pst != null) { pst.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(PropertiesExample.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 我們連接到`testdb`,然后從`CARS`表中選擇所有汽車。 該示例的配置數據是從`db.properties`文件中讀取的。 ```java Properties props = new Properties(); FileInputStream in = null; try { in = new FileInputStream("src/main/resources/db.properties"); props.load(in); ``` 創建`Properties`類。 數據是從名為`db.properties`的文件中加載的,其中包含我們的配置數據。 ```java String url = props.getProperty("db.url"); String user = props.getProperty("db.user"); String passwd = props.getProperty("db.passwd"); ``` 使用`getProperty()`方法檢索這些值。 ```java con = DriverManager.getConnection(url, user, passwd); ``` 請注意,在默認的 Derby 配置中,密碼將被忽略。 ## 預備語句 現在,我們將以預備語句來關注自己。 在編寫預備語句時,我們使用占位符,而不是直接將值寫入語句中。 預準備的語句可提高安全性和性能。 在 Java 中,`PreparedStatement`是代表預編譯的 SQL 語句的對象。 Prepared.java ```java package com.zetcode; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; public class Prepared { public static void main(String[] args) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; String url = "jdbc:derby:testdb;user=USER12"; int price = 58000; int id = 2; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); pst = con.prepareStatement("UPDATE CARS SET PRICE = ? WHERE ID = ?"); pst.setInt(1, price); pst.setInt(2, id); pst.executeUpdate(); DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(Prepared.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (rs != null) { rs.close(); } if (pst != null) { pst.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(Prepared.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 我們更改 ID 等于 2 的汽車的價格。 ```java int price = 58000; int id = 2; ``` 這些是將要預備語句的值。 這些值可能來自用戶,并且來自用戶的所有內容都應被視為潛在危險。 ```java pst = con.prepareStatement("UPDATE CARS SET PRICE = ? WHERE ID = ?"); ``` 在這里,我們創建一個預備語句。 在編寫預備語句時,我們使用占位符,而不是直接將值寫入語句中。 預備語句更快,并且可以防止 SQL 注入攻擊。 `?`是一個占位符,稍后將填充。 ```java pst.setInt(1, price); pst.setInt(2, id); ``` 值綁定到占位符。 ```java pst.executeUpdate(); ``` 執行預備語句。 當我們不希望返回任何數據時,我們使用語句對象的`executeUpdate()`方法。 這是當我們創建數據庫或執行`INSERT`,`UPDATE`和`DELETE`語句時。 ```java ij> SELECT * FROM CARS WHERE ID=2; ID |NAME |PRICE ------------------------------------------------------ 2 |Mercedes |58000 1 row selected ``` 運行示例后,我們使用`ij`工具檢查結果。 ## 列標題 接下來,我們將展示如何使用數據庫表中的數據打印列標題。 我們將列名稱稱為元數據。 元數據是有關數據庫中核心數據的數據。 ColumnHeaders.java ```java package com.zetcode; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.Formatter; import java.util.logging.Level; import java.util.logging.Logger; public class ColumnHeaders { public static void main(String[] args) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; String url = "jdbc:derby:testdb;user=USER12"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); String query = "SELECT NAME, TITLE From AUTHORS, " + "Books WHERE AUTHORS.ID=BOOKS.AUTHOR_ID"; pst = con.prepareStatement(query); rs = pst.executeQuery(); ResultSetMetaData meta = rs.getMetaData(); String colname1 = meta.getColumnName(1); String colname2 = meta.getColumnName(2); Formatter fmt1 = new Formatter(); fmt1.format("%-21s%s", colname1, colname2); System.out.println(fmt1); while (rs.next()) { Formatter fmt2 = new Formatter(); fmt2.format("%-21s", rs.getString(1)); System.out.print(fmt2); System.out.println(rs.getString(2)); } DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(ColumnHeaders.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (rs != null) { rs.close(); } if (pst != null) { pst.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(ColumnHeaders.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 在此程序中,我們從`AUTHORS`表中選擇作者,并從`BOOKS`表中選擇他們的書。 我們打印結果集中返回的列的名稱。 我們格式化輸出。 用于創建表的 SQL 文件位于本教程的第一章中。 ```java String query = "SELECT NAME, TITLE From AUTHORS, " + "Books WHERE AUTHORS.ID=BOOKS.AUTHOR_ID"; ``` 這是將作者與他們的書聯系在一起的 SQL 語句。 ```java ResultSetMetaData meta = rs.getMetaData(); ``` 要獲取列名,我們需要獲取`ResultSetMetaData`。 它是一個對象,可用于獲取有關`ResultSet`對象中列的類型和屬性的信息。 `ResultSetMetaData`是通過`getMetaData()`方法從`ResultSet`獲得的。 ```java String colname1 = meta.getColumnName(1); String colname2 = meta.getColumnName(2); ``` 從獲得的元數據中,我們使用`getColumnName()`方法獲得列名。 ```java Formatter fmt1 = new Formatter(); fmt1.format("%-21s%s", colname1, colname2); System.out.println(fmt1); ``` 我們將列名稱打印到控制臺。 `Formatter`對象格式化數據。 ```java while (rs.next()) { Formatter fmt2 = new Formatter(); fmt2.format("%-21s", rs.getString(1)); System.out.print(fmt2); System.out.println(rs.getString(2)); } ``` 我們將數據打印到控制臺。 我們再次使用`Formatter`對象來格式化數據。 第一列為 21 個字符,并在左側對齊。 ```java NAME TITLE Jack London Call of the Wild Jack London Martin Eden Honore de Balzac Old Goriot Honore de Balzac Cousin Bette Lion Feuchtwanger Jew Suess Emile Zola Nana Emile Zola The Belly of Paris Truman Capote In Cold blood Truman Capote Breakfast at Tiffany Mar 22, 2017 12:52:56 PM com.zetcode.ColumnHeaders main INFO: Derby shut down normally java.sql.SQLException: Derby system shutdown. ... ``` 這是示例的輸出。 ## 寫入圖像 有些人喜歡將其圖像放入數據庫中,有些人則希望將其保留在文件系統中以供其應用使用。 當我們處理大量圖像時,會出現技術難題。 圖像是二進制數據。 Derby 具有一種特殊的數據類型來存儲稱為`BLOB`(二進制大對象)的二進制數據。 我們為此示例和以下示例創建一個名為`IMAGES`的新表。 ```java ij> CREATE TABLE IMAGES(ID INT PRIMARY KEY, DATA BLOB); 0 rows inserted/updated/deleted ``` `DATA`列具有`BLOB`類型。 在那里,我們將插入編碼的二進制數據。 WriteImage.java ```java package com.zetcode; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; public class WriteImage { public static void main(String[] args) { Connection con = null; PreparedStatement pst = null; String url = "jdbc:derby:testdb;user=USER12"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); File imgFile = new File("woman.jpg"); try (FileInputStream fin = new FileInputStream(imgFile)) { con = DriverManager.getConnection(url); pst = con.prepareStatement("INSERT INTO IMAGES(ID, DATA) VALUES(1, ?)"); pst.setBinaryStream(1, fin, (int) imgFile.length()); pst.executeUpdate(); } DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (FileNotFoundException ex) { Logger lgr = Logger.getLogger(WriteImage.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); } catch (SQLException ex) { Logger lgr = Logger.getLogger(WriteImage.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } catch (IOException ex) { Logger.getLogger(WriteImage.class.getName()).log(Level.SEVERE, null, ex); } finally { try { if (pst != null) { pst.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(WriteImage.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 在此示例中,我們從當前工作目錄中讀取 JPG 圖像,然后插入`IMAGES`表中。 ```java File imgFile = new File("woman.jpg"); try (FileInputStream fin = new FileInputStream(imgFile)) { ``` 我們為圖像文件創建一個`File`對象。 要從該文件讀取字節,我們創建一個`FileInputStream`對象。 ```java pst = con.prepareStatement("INSERT INTO IMAGES(ID, DATA) VALUES(1, ?)"); ``` 該 SQL 語句將圖像插入`Images`表。 ```java pst.setBinaryStream(1, fin, (int) img.length()); ``` 二進制流設置為預備語句。 `setBinaryStream()`方法的參數是要綁定的參數索引,輸入流和流中的字節數。 ```java pst.executeUpdate(); ``` 我們使用`executeUpdate()`方法執行該語句。 ## 讀取圖像 在前面的示例中,我們已將圖像插入數據庫表中。 現在,我們將從表中讀取圖像。 ReadImage.java ```java package com.zetcode; import java.io.FileOutputStream; import java.io.IOException; import java.sql.Blob; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; public class ReadImage { public static void main(String[] args) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; String url = "jdbc:derby:testdb;user=USER12"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); System.out.println(System.getProperty("user.dir")); con = DriverManager.getConnection(url); String query = "SELECT DATA FROM IMAGES WHERE ID = 1"; pst = con.prepareStatement(query); rs = pst.executeQuery(); rs.next(); String fileName = "src/main/resources/woman.jpg"; try (FileOutputStream fos = new FileOutputStream(fileName)) { Blob blob = rs.getBlob("DATA"); int len = (int) blob.length(); byte[] buf = blob.getBytes(1, len); fos.write(buf, 0, len); } DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (IOException ex) { Logger lgr = Logger.getLogger(ReadImage.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); } catch (SQLException ex) { Logger lgr = Logger.getLogger(ReadImage.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (rs != null) { rs.close(); } if (pst != null) { pst.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(ReadImage.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 我們從`IMAGES`表中讀取了一張圖像。 ```java String query = "SELECT DATA FROM IMAGES WHERE ID = 1"; ``` 選擇一條記錄。 ```java try (FileOutputStream fos = new FileOutputStream(fileName)) { ``` 創建`FileOutputStream`對象以寫入文件。 它旨在寫入原始字節流,例如圖像數據。 ```java Blob blob = result.getBlob("DATA"); ``` 我們通過調用`getBlob()`方法從`DATA`列中獲取圖像數據。 ```java int len = (int) blob.length(); ``` 我們找出斑點數據的長度。 換句話說,我們得到字節數。 ```java byte[] buf = blob.getBytes(1, len); ``` `getBytes()`方法以字節數組的形式檢索`BLOB`對象的所有字節。 ```java fos.write(buf, 0, len); ``` 字節被寫入輸出流。 該映像是在文件系統上創建的。 ## 事務支持 事務是針對一個或多個數據庫中數據的數據庫操作的基本單位。 事務中所有 SQL 語句的影響可以全部提交給數據庫,也可以全部回滾。 創建連接后,它處于自動提交模式。 這意味著每個單獨的 SQL 語句都被視為事務,并在執行后立即自動提交。 對于所有 JDBC 驅動程序(包括 Derby 的驅動程序)都是如此。 要開始新的事務,我們關閉自動提交。 在直接 SQL 中,事務以`BEGIN TRANSACTION`語句開始,并以`END TRANSACTION` / `COMMIT`語句結束。 在 Derby 中,這些語句是`BEGIN`和`COMMIT`。 但是,在使用驅動程序時,將省略這些語句。 它們由驅動處理。 確切的細節是特定于驅動程序的。 例如,`psycopg2` Python 驅動程序在第一個 SQL 語句之后啟動事務。 如果要使用自動提交模式,則必須將`autocommit`屬性設置為 True。 相反,默認情況下,JDBC 驅動程序處于自動提交模式。 并且要開始新事務,必須關閉自動提交。 Transaction.java ```java package com.zetcode; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; import java.util.logging.Logger; public class Transaction { public static void main(String[] args) { Connection con = null; Statement st = null; String url = "jdbc:derby:testdb;user=USER12"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); st = con.createStatement(); con.setAutoCommit(false); st.executeUpdate("UPDATE AUTHORS SET NAME = 'Leo Tolstoy' " + "WHERE Id = 1"); st.executeUpdate("UPDATE BOOKS SET TITLE = 'War and Peace' " + "WHERE Id = 1"); st.executeUpdate("UPDATE BOOKS SET TITL = 'Anna Karenina' " + "WHERE Id = 2"); con.commit(); DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(Transaction.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { if (con != null) { try { con.rollback(); } catch (SQLException ex1) { lgr.log(Level.WARNING, ex1.getMessage(), ex1); } } lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (st != null) { st.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(Transaction.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 在此程序中,我們想在`AUTHORS`表的第一行中更改作者的姓名。 我們還必須更改與該作者相關的書籍。 如果我們更改作者但不更改作者的書,則數據已損壞。 ```java con.setAutoCommit(false); ``` 要處理事務,必須將`autocommit`設置為`false`。 默認情況下,數據庫連接處于自動提交模式。 在這種模式下,每條語句在執行后都會立即提交給數據庫。 聲明無法撤消。 當自動提交關閉時,我們通過調用`commit()`提交更改,或通過調用`rollback()`方法將其回滾。 ```java st.executeUpdate("UPDATE BOOKS SET TITL = 'Anna Karenina' " + "WHERE Id = 2"); ``` 第三個 SQL 語句有一個錯誤。 `BOOKS`表中沒有`TITL`列。 ```java con.commit(); ``` 如果沒有異常,則提交事務。 如果自動提交關閉,則必須顯式調用`commit()`方法。 ```java if (con != null) { try { con.rollback(); } catch (SQLException ex1) { lgr.log(Level.WARNING, ex1.getMessage(), ex1); } } ``` 如果發生 Derby 系統關閉以外的異常,則事務將回滾。 沒有更改提交到數據庫。 ```java Mar 22, 2017 2:00:40 PM com.zetcode.Transaction main SEVERE: 'TITL' is not a column in table or VTI 'USER12.BOOKS'. java.sql.SQLSyntaxErrorException: 'TITL' is not a column in table or VTI 'USER12.BOOKS'. ``` 執行失敗,并顯示`'TITL' is not a column in table`消息。 引發異常。 事務已回滾,并且未進行任何更改。 ```java ij> CONNECT 'jdbc:derby:testdb'; ij> SET CURRENT SCHEMA = USER12; ij> SELECT NAME, TITLE FROM AUTHORS, BOOKS WHERE AUTHORS.ID = BOOKS.AUTHOR_ID; NAME |TITLE ------------------------------------------------------------ Jack London |Call of the Wild Jack London |Martin Eden Honore de Balzac |Old Goriot Honore de Balzac |Cousin Bette Lion Feuchtwanger |Jew Suess Emile Zola |Nana Emile Zola |The Belly of Paris Truman Capote |In Cold blood Truman Capote |Breakfast at Tiffany 9 rows selected ``` 數據未損壞。 但是,如果沒有事務,數據是不安全的。 NonTransaction.java ```java package com.zetcode; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; import java.util.logging.Logger; public class NonTransaction { public static void main(String[] args) { Connection con = null; Statement st = null; String url = "jdbc:derby:testdb;user=USER12"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); st = con.createStatement(); st.executeUpdate("UPDATE AUTHORS SET NAME = 'Leo Tolstoy' " + "WHERE Id = 1"); st.executeUpdate("UPDATE BOOKS SET TITLE = 'War and Peace' " + "WHERE Id = 1"); st.executeUpdate("UPDATE BOOKS SET TITL = 'Anna Karenina' " + "WHERE Id = 2"); DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(NonTransaction.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (st != null) { st.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(NonTransaction.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 我們有同樣的例子。 這次,沒有事務支持。 ```java Mar 22, 2017 2:08:40 PM com.zetcode.NonTransaction main SEVERE: 'TITL' is not a column in table or VTI 'USER12.BOOKS'. java.sql.SQLSyntaxErrorException: 'TITL' is not a column in table or VTI 'USER12.BOOKS'. ... ij> CONNECT 'jdbc:derby:testdb'; ij> SET CURRENT SCHEMA = USER12; ij> SELECT NAME, TITLE FROM AUTHORS, BOOKS WHERE AUTHORS.ID = BOOKS.AUTHOR_ID; NAME |TITLE ---------------------------------------------------------------- Leo Tolstoy |War and Peace Leo Tolstoy |Martin Eden Honore de Balzac |Old Goriot Honore de Balzac |Cousin Bette Lion Feuchtwanger |Jew Suess Emile Zola |Nana Emile Zola |The Belly of Paris Truman Capote |In Cold blood Truman Capote |Breakfast at Tiffany 9 rows selected ``` 再次引發異常。 列夫·托爾斯泰(Leo Tolstoy)沒有寫馬丁·伊登(Martin Eden):數據已損壞。 ## 批量更新 當我們需要使用多個語句更新數據時,可以使用批處理更新。 批量更新可用于`INSERT`,`UPDATE`,`DELETE`語句以及`CREATE TABLE`和`DROP TABLE`語句。 BatchUpdates.java ```java package com.zetcode; import java.sql.*; import java.util.logging.Level; import java.util.logging.Logger; public class BatchUpdates { public static void main(String[] args) { Connection con = null; Statement st = null; ResultSet rs = null; String url = "jdbc:derby:testdb;user=USER12"; try { System.setProperty("derby.system.home", "/home/janbodnar/.derby"); con = DriverManager.getConnection(url); con.setAutoCommit(false); st = con.createStatement(); st.addBatch("DELETE FROM CARS"); st.addBatch("INSERT INTO CARS VALUES(1, 'Audi', 52642)"); st.addBatch("INSERT INTO CARS VALUES(2, 'Mercedes', 57127)"); st.addBatch("INSERT INTO CARS VALUES(3, 'Skoda', 9000)"); st.addBatch("INSERT INTO CARS VALUES(4, 'Volvo', 29000)"); st.addBatch("INSERT INTO CARS VALUES(5, 'Bentley', 350000)"); st.addBatch("INSERT INTO CARS VALUES(6, 'Citroen', 21000)"); st.addBatch("INSERT INTO CARS VALUES(7, 'Hummer', 41400)"); st.addBatch("INSERT INTO CARS VALUES(8, 'Volkswagen', 21600)"); st.addBatch("INSERT INTO CARS VALUES(9, 'Jaguar', 95000)"); int counts[] = st.executeBatch(); con.commit(); System.out.println("Committed " + counts.length + " updates"); DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException ex) { Logger lgr = Logger.getLogger(BatchUpdates.class.getName()); if (((ex.getErrorCode() == 50000) && ("XJ015".equals(ex.getSQLState())))) { lgr.log(Level.INFO, "Derby shut down normally", ex); } else { if (con != null) { try { con.rollback(); } catch (SQLException ex1) { lgr.log(Level.WARNING, ex1.getMessage(), ex1); } } lgr.log(Level.SEVERE, ex.getMessage(), ex); } } finally { try { if (rs != null) { rs.close(); } if (st != null) { st.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(BatchUpdates.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } } ``` 這是用于批處理更新的示例程序。 我們從`CARS`表中刪除所有行,并在其中插入 9 行。 ```java con.setAutoCommit(false); ``` 進行批處理更新時,應始終關閉自動提交。 ```java st.addBatch("DELETE FROM CARS"); st.addBatch("INSERT INTO CARS VALUES(1, 'Audi', 52642)"); st.addBatch("INSERT INTO CARS VALUES(2, 'Mercedes', 57127)"); st.addBatch("INSERT INTO CARS VALUES(3, 'Skoda', 9000)"); ... ``` 我們使用`addBatch()`方法向該語句添加新命令。 ```java int counts[] = st.executeBatch(); ``` 添加所有命令后,我們調用`executeBatch()`進行批量更新。 該方法返回已提交更改的數組。 ```java con.commit(); ``` 批處理更新在事務中提交。 ```java ij> SELECT * FROM CARS; ID |NAME |PRICE ------------------------------------------------------ 1 |Audi |52642 2 |Mercedes |57127 3 |Skoda |9000 4 |Volvo |29000 5 |Bentley |350000 6 |Citroen |21000 7 |Hummer |41400 8 |Volkswagen |21600 9 |Jaguar |95000 ``` 我們已經成功地重新創建了`CARS`表。 在本章中,我們使用 Java 和 Derby 進行了一些 JDBC 編程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看