Java操作數據庫——使用JDBC連接數據庫


Java操作數據庫——使用JDBC連接數據庫

摘要:本文主要學習了如何使用JDBC連接數據庫。

背景

數據持久化

數據持久化就是把數據保存到可掉電式存儲設備中以供之后使用。大多數情況下,特別是企業級應用,數據持久化意味着將內存中的數據保存到硬盤上加以“固化”,而持久化的實現過程大多通過各種關系數據庫來完成。

持久化的主要應用是將內存中的數據存儲在關系型數據庫中,當然也可以存儲在磁盤文件、XML數據文件中。

基礎

概念

JDBC的全稱是Java Database Connectivity,意為Java和數據庫的連接。

JDBC是SUN公司提供的一套操作數據庫的接口規范,定義了用來訪問數據庫的標准Java類庫,使用這個類庫可以更加方便地訪問數據庫資源。

程序員在使用數據庫的時候,需要安裝數據庫驅動,不同的數據庫的驅動也是不同的。所以為了程序員開發方便,SUN公司提供了一套接口,讓數據庫廠商實現這些接口,程序員只需要使用這個接口就可以操作不同的數據庫,不需要關注底層數據庫驅動的安裝,從而大大簡化和加快了開發過程。

架構

JDBC接口包括兩個層次:

JDBC API:即面向應用的API,是一個抽象的接口,供應用程序開發人員使用,提供了程序到JDBC管理器的連接。

JDBC Driver API:即面向數據庫驅動的API,需要開發商去實現這個接口,提供了JDBC管理器到數據庫驅動程序的連接。

規范

主要有四個核心對象:

DriverManager類(java.sql.DriverManager):用於注冊驅動,創建連接對象。

Connection接口(java.sql.Connection):表示與數據庫創建的連接。

Statement接口(java.sql.Statement):執行數據庫SQL語句,並返回相應結果的對象。

ResultSet接口(java.sql.ResultSet):結果集或一張虛擬表,用於存儲表數據的對象。

其中,Statement接口還有兩個子接口:

PreparedStatement接口(java.sql.PreparedStatement):預編譯對象,是Statement接口的子接口,用於解決sql的注入問題。

CallableStatement接口(java.sql.CallableStatement):支持帶參數的SQL操作,支持調用存儲過程,是PreparedStatement接口的子接口。

連接數據庫

下面的說明以連接MySQL數據庫為例。

准備工作

擁有一個可以正常訪問的MySQL數據庫,已經可以登錄使用的用戶名和密碼。

建立一個准備連接數據庫的項目。

導入jar包

導入Java連接MySQL所用到的jar包,這個jar包通常是由數據庫的廠商提供的,這里下載的是 mysql-connector-java-5.1.32.jar 這個包。

那Eclipse為例,在項目上右鍵,然后點擊Properties:

然后在彈出的頁面左側找到 Java Build Path 目錄並進入,選擇 Libraries 標簽頁,找到標簽頁右側的 Add External JARs... 按鈕:

找到下載的jar包,點擊打開:

可以看到jar包被成功導入到項目中:

點擊OK完成導入。

加載驅動

加載數據庫驅動的方法是調用Class類的靜態方法forName。語法格式如下:

1 public static Class<?> forName(String className)

其中,傳入的參數className是每個數據庫廠商各自提供的一個驅動程序名稱。

不同的數據庫,驅動程序名稱如下:

1 MySQL驅動:com.mysql.jdbc.Drive
2 Oracle驅動:oracle.jdbc.driver.OracleDriver
3 SQLServer驅動:com.microsoft.sqlserver.jdbc.SQLServerDriver
4 PostgreSQL驅動:org.postgresql.Driver
5 DB2驅動:com.ibm.db2.jdbc.net.DB2Driver
6 Sybase驅動:com.sybase.jdbc.SybDriver

建立連接

使用DriverManager類的靜態方法getConnection建立到指定數據庫的連接。語法格式如下:

1 public static Connection getConnection(String url, String user, String password)

url是SUN公司與數據庫廠商之間的一種協議,user是連接數據庫的用戶名,password是用戶名對應的密碼。

不同的數據庫,url協議的格式如下:

1 MySQL格式:jdbc:mysql://地址或主機名:端口號/數據庫名
2 Oracle格式:jdbc:oracle:thin:@地址或主機名:端口號:數據庫名
3 SQLServer格式:jdbc:sqlserver://地址或主機名:端口號;databaseName=數據庫名
4 PostgreSQL格式:jdbc:postgresql://地址或主機名:端口號/數據庫名
5 DB2格式:jdbc:db2:地址或主機名:端口號/數據庫名
6 Sybase格式:jdbc:sybase:Tds:地址或主機名:端口號/數據庫名

如果是在本機並且用的是默認的端口號,可以將地址和端口號省略:

1 jdbc:mysql:///數據庫名

建議url中的文件編碼、數據庫連接編碼、數據庫編碼保持一致,向數據庫中添加數據時,連接參數最好包含Unicode字符支持,這樣添加的字符就能被數據庫識別並且正常顯示了:

1 jdbc:mysql://地址或主機名:端口號/數據庫名?useUnicode=true&characterEncoding=UTF-8

至此,就成功獲取到了連接MySQL數據庫的Connection對象。

執行語句

獲取到連接之后,使用Connection接口的createStatement方法獲取Statement對象。語法格式如下:

1 Statement createStatement()

獲取到了Statement對象之后,使用executeQuery方法執行查詢語句得到ResultSet類型的結果集,使用executeUpdate方法執行增加、刪除、修改語句得到int類型的記錄數。

釋放連接

數據庫連接Connection是非常稀有的資源,用完后必須馬上釋放,如果Connection不能及時正確的關閉將導致系統宕機。Connection的使用原則是盡量晚創建,盡量早的釋放。

釋放的方法是通過調用Connection的close方法,語法格式如下:

1 void close()

一次完整的操作數據庫的流程包括加載驅動、建立連接、執行語句、釋放連接。其中,加載驅動只執行一次即可,建立的連接用完之后必須馬上釋放。

連接數據庫實例

在程序里配置連接信息

完整代碼如下:

 1 public static void main(String[] args) {
 2     try {
 3         Class.forName("com.mysql.jdbc.Driver");
 4     } catch (ClassNotFoundException e) {
 5         e.printStackTrace();
 6     }
 7     Connection conn = null;
 8     try {
 9         String url = "jdbc:mysql://192.168.35.128:3306/demo";
10         String user = "root";
11         String password = "123456";
12         conn = DriverManager.getConnection(url, user, password);
13     } catch (Exception e) {
14         e.printStackTrace();
15     } finally {
16         try {
17             conn.close();
18         } catch (SQLException e) {
19             e.printStackTrace();
20         }
21     }
22 }

在配置文件里配置連接信息

配置文件 jdbc.properties 在 src 目錄下,和當前的源文件的根目錄 package jdbc; 平級,內容如下:

1 driverClass=com.mysql.jdbc.Driver
2 url="jdbc:mysql://192.168.35.128:3306/demo"
3 user=root
4 password=123456

完整代碼如下:

 1 public static void main(String[] args) {
 2     Properties pros = new Properties();
 3     try {
 4         pros.load(TestConnection.class.getClassLoader().getResourceAsStream("jdbc.properties"));
 5     } catch (IOException e) {
 6         e.printStackTrace();
 7     }
 8     try {
 9         Class.forName(pros.getProperty("driverClass"));
10     } catch (ClassNotFoundException e) {
11         e.printStackTrace();
12     }
13     Connection conn = null;
14     try {
15         String url = pros.getProperty("url");
16         String user = pros.getProperty("user");
17         String password = pros.getProperty("password");
18         conn = DriverManager.getConnection(url, user, password);
19     } catch (Exception e) {
20         e.printStackTrace();
21     } finally {
22         try {
23             conn.close();
24         } catch (SQLException e) {
25             e.printStackTrace();
26         }
27     }
28 }

增刪改查

查詢

使用實例:

 1 public static void main(String[] args) {
 2     try {
 3         Class.forName("com.mysql.jdbc.Driver");
 4     } catch (ClassNotFoundException e) {
 5         e.printStackTrace();
 6     }
 7     Connection conn = null;
 8     Statement stmt = null;
 9     ResultSet rs = null;
10     try {
11         String url = "jdbc:mysql://192.168.35.128:3306/demo";
12         String user = "root";
13         String password = "123456";
14         conn = DriverManager.getConnection(url, user, password);
15         stmt = conn.createStatement();
16         rs = stmt.executeQuery("select * from student");
17         while (rs.next()) {
18             System.out.println(rs.getInt("id") + "\t" + rs.getString(2) + "\t" + rs.getString(3) + "\t" + rs.getString("address"));
19         }
20     } catch (Exception e) {
21         e.printStackTrace();
22     } finally {
23         try {
24             rs.close();
25         } catch (SQLException e) {
26             e.printStackTrace();
27         }
28         try {
29             stmt.close();
30         } catch (SQLException e) {
31             e.printStackTrace();
32         }
33         try {
34             conn.close();
35         } catch (SQLException e) {
36             e.printStackTrace();
37         }
38     }
39 }

增加、修改、刪除

使用實例:

 1 public static void main(String[] args) {
 2     try {
 3         Class.forName("com.mysql.jdbc.Driver");
 4     } catch (ClassNotFoundException e) {
 5         e.printStackTrace();
 6     }
 7     Connection conn = null;
 8     Statement stmt = null;
 9     try {
10         String url = "jdbc:mysql://192.168.35.128:3306/demo";
11         String user = "root";
12         String password = "123456";
13         conn = DriverManager.getConnection(url, user, password);
14         stmt = conn.createStatement();
15         int count = stmt.executeUpdate("delete from student where id = 903");
16         System.out.println("受影響的行數:" + count);
17     } catch (Exception e) {
18         e.printStackTrace();
19     } finally {
20         try {
21             stmt.close();
22         } catch (SQLException e) {
23             e.printStackTrace();
24         }
25         try {
26             conn.close();
27         } catch (SQLException e) {
28             e.printStackTrace();
29         }
30     }
31 }

Statement接口

Statement接口是通過Connection的createStatement方法獲取的,用來執行SQL語句並返回相應的結果。語法格式如下:

1 Statement createStatement()

使用完之后需要手動關閉Statement對象。

PreparedStatement接口

PreparedStatement接口是通過Connection的preparedStatement方法獲取的,是Statement的子接口,表示一條預編譯過的SQL語句。語法格式如下:

1 PreparedStatement prepareStatement(String sql)

傳入的SQL語句中的參數用問號“?”來表示,調用PreparedStatement對象的setXxx方法來設置這些參數。setXxx方法有兩個參數,第一個參數是要設置的參數索引(從1開始),第二個是設置的參數值。

使用Statement可能會因為字符串拼接導致被人SQL注入攻擊,但使用PreparedStatement不需要拼接字符串,而是使用占位符的方法,有效避免了SQL注入攻擊的問題。

使用舉例:

1 pstmt = conn.prepareStatement("select * from student where id = ?");
2 pstmt.setInt(1, 904);
3 rs = pstmt.executeQuery();
4 while (rs.next()) {
5     System.out.println(rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3) + "\t" + rs.getString("address"));
6 }

ResultSet接口

使用Statement接口的executeQuery方法執行傳入的查詢語句,並得到ResultSet類型的結果集。語法格式如下:

1 ResultSet executeQuery(String sql)

ResultSet接口由數據庫廠商實現,以邏輯表格的形式封裝了執行數據庫操作的結果集。

ResultSet對象維護了一個指向當前數據行的游標,游標默認從1開始,可以通過next方法移動到下一行。

使用完之后需要手動關閉ResultSet對象。

常用方法:

 1 byte getByte(int columnIndex) throws SQLException;
 2 byte getByte(String columnLabel) throws SQLException;
 3 byte[] getBytes(int columnIndex) throws SQLException;
 4 byte[] getBytes(String columnLabel) throws SQLException;
 5 short getShort(int columnIndex) throws SQLException;
 6 short getShort(String columnLabel) throws SQLException;
 7 int getInt(int columnIndex) throws SQLException;
 8 int getInt(String columnLabel) throws SQLException;
 9 long getLong(int columnIndex) throws SQLException;
10 long getLong(String columnLabel) throws SQLException;
11 float getFloat(int columnIndex) throws SQLException;
12 float getFloat(String columnLabel) throws SQLException;
13 double getDouble(int columnIndex) throws SQLException;
14 double getDouble(String columnLabel) throws SQLException;
15 String getString(int columnIndex) throws SQLException;
16 String getString(String columnLabel) throws SQLException;
17 boolean getBoolean(int columnIndex) throws SQLException;
18 boolean getBoolean(String columnLabel) throws SQLException;
19 java.sql.Date getDate(int columnIndex) throws SQLException;
20 java.sql.Date getDate(String columnLabel) throws SQLException;
21 java.sql.Time getTime(int columnIndex) throws SQLException;
22 java.sql.Time getTime(String columnLabel) throws SQLException;
23 java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException;
24 java.sql.Timestamp getTimestamp(String columnLabel) throws SQLException;
25 Object getObject(int columnIndex) throws SQLException;
26 Object getObject(String columnLabel) throws SQLException;
27 
28 boolean next() throws SQLException;
29 void close() throws SQLException;
30 
31 ResultSetMetaData getMetaData() throws SQLException;

使用舉例:

1 stmt = conn.createStatement();
2 rs = stmt.executeQuery("select * from student");
3 while (rs.next()) {
4     System.out.println(rs.getInt("id") + "\t" + rs.getString(2) + "\t" + rs.getString(3) + "\t" + rs.getString("address"));
5 }

ResultSetMetaData接口

ResultSetMetaData對象可以用來獲取ResultSet對象中列的類型和屬性信息。

常用方法:

1 int getColumnCount() throws SQLException;
2 int getColumnTypeName(int column) throws SQLException;
3 String getColumnLabel(int column) throws SQLException;
4 String getColumnName(int column) throws SQLException;

使用舉例:

1 stmt = conn.createStatement();
2 rs = stmt.executeQuery("select * from student");
3 while (rs.next()) {
4     ResultSetMetaData rsmd = rs.getMetaData();
5     System.out.println(rsmd.getColumnName(1) + "=" + rs.getInt("id") + "\t" + rsmd.getColumnName(2) + "=" + rs.getString(2));
6 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM