鑒於linux系統下安裝oracle數據庫過於麻煩,而相關的java連接mysql基本方法的參考文章過少且參差不齊,故本人查閱了一些書和網絡資料寫下此文章。
從數據庫環境搭建、基本語法到封裝工具類全過程,可作為參考。轉載請注明來源。
Content:
-
常用的JDBC API
-
數據庫環境的搭建
-
建立數據庫連接
-
數據庫訪問優化
一. 常用的JDBC API
1. DriverManager類 : 數據庫管理類,用於管理一組JDBC驅動程序的基本服務。應用程序和數據庫之間可以通過此類建立連接。常用的靜態方法如下
- static connection getConnection(String url, String user, String password) - 獲取指定URL的數據庫連接
- static Driver getDriver(String url) - 返回能夠打開url所制定的數據庫的驅動程序
2. Connection接口 : 用於連接數據庫。每個Connection對象代表一個數據庫連接會話。一個應用程序可與多個數據庫建立連接。常用的靜態方法如下
- void close() - 斷開連接,釋放此Connection對象的數據庫和JDBC資源
- Statement createStatement() - 創建一個Statement對象來將SQL語句發送到數據庫
- void commit() - 用於提交SQL語句,確認從上一次提交/回滾以來進行的所有更改
- boolean isClosed() - 這個就不解釋了
- CallableStatement prepareCall(String sql) - 創建一個CallableStatement對象來調用數據庫存儲過程
- PreparedStatement prepareStatement(String sql) - 創建一個PreparedStatement對象來將參數化的SQL語句發送到數據庫
- void rollback() - 用於取消SQL語句,取消在當前事物中進行的所有更改
3. Statement接口 :Statement接口一般用於執行SQL語句。Statement接口的主要功能是將SQL語句傳送給數據庫,並返回SQL語句的執行結果。
- boolean execute(String sql) - 執行給定的SQL語句,該語句可能返回多個結果
- ResultSet executeQuery(String sql) - 執行給定的SQL語句,該語句返回單個ResultSet對象
- int executeUpdate(String sql) - 執行和給定SQL語句,該語句可能為INSERT、UPDATE或DELETE語句,或者不返回任何內容的SQL語句(如SQL DDL 語句)
- Connection getConnection() - 獲取生成此Statement對象的Connection對象
4. ResultSet接口 :用於封裝結果集對象,該對象包含訪問查詢結果的方法。 使用Statement中的executeQuery()方法可以返回有符合查詢條件的記錄。
- boolean first() - 將游標移動到結果集的第一行
- boolean next() - 將游標移動到結果集的下一行
- boolean previous() - 將游標移動到結果集的上一行
- void close() - 釋放此ResultSet對象的數據庫和JDBC資源
注: 以上僅是列舉后面要用到的方法,更多方法請查詢相關文檔。
二. 數據庫環境的搭建
在ubuntu 17.10系統下安裝並配置mysql(ubuntu系統下安裝mysql非常簡單,過程略),使用eclispe開發環境,需要下載並配置mysql的驅動jar包(可參考:http://blog.csdn.net/Kindle_code/article/details/49531977),使用MySQL Workbench圖形化軟件管理數據庫,執行以下語句創建一個本地數據庫
1.創建數據庫
create database CS; use CS; create table Userdetails( id int primary key, -- 主鍵id username varchar(50) not null, -- 用戶名 password varchar(50) not null, sex char(1) not null -- 性別,1:男,0:女 ) insert into Userdetails(id,username,password,sex) values(1,'zhangsan','zs123',1); insert into Userdetails(id,username,password,sex) values(2,'lisi','lisi123',1); insert into Userdetails(id,username,password,sex) values(3,'wangwu','wangwu123',1); insert into Userdetails(id,username,password,sex) values(4,'maliu','maliu123',1); insert into Userdetails(id,username,password,sex) values(5,'lsy','lsy123',1);
SQL語法請查閱相關文檔,要注意 MSSQL 、Oracle、MySQL 這三個常見的數據庫在語法上是有一定區別的
執行結果:
三. 建立數據庫連接
1.加載數據庫驅動
Class.forName("com.mysql.jdbc.Driver");
2.建立數據庫連接
String url = "jdbc:mysql://localhost:3306/CS?useSSL=false"; //注意因為版本問題要添加后面的useSSL語句 String user = "root"; String password = "haha"; Connection conn = DriverManager.getConnection(url, user, password);
3.創建Statement對象
- createStatement()方法——用於創建一個基本的Statement對象;
- prepareStatement(String sql)方法——根據參數化的SQL語句創建一個預編譯的PreparedStatement對象;
- prepareCall(String sql)方法——根據SQL語句來創建一個CallableStatement對象,用於調用數據庫的存儲過程.
Statement stmt = conn.createStatement();
4.執行SQL語句並訪問結果集
String sql = "SELECT id,username FROM Userdetails"; ResultSet rs = stmt.executeQuery(sql); while(rs.next()) { System.out.println(rs.getString(1) + " " + rs.getString("username")); }
當使用getXXX()方法訪問結果集中的數據時,可通過列索引或列名來獲取游標所指行中的列數據
如: getXXX(列索引) / 如getString(...)等
getXXX("列名")
完整實例代碼如下:
import java.sql.*; public class ExecuteDemo { final static String url = "jdbc:mysql://localhost:3306/CS?useSSL=false"; final static String user = "root"; final static String password = "haha"; public static void main(String [] args) { try { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection(url, user, password); System.out.println("連接數據庫成功!"); Statement stmt = conn.createStatement(); String sql = "SELECT id,username FROM Userdetails"; ResultSet rs = stmt.executeQuery(sql); System.out.println("查詢成功!"); while(rs.next()) { System.out.println(rs.getString(1) + " " + rs.getString("username")); } rs.close(); stmt.close(); conn.close(); } catch(ClassNotFoundException e) { e.printStackTrace(); } catch(SQLException e) { e.printStackTrace(); } } }
執行結果:
四. 數據庫訪問優化
編寫了一部分數據庫訪問和執行代碼后能夠發現一個問題:在訪問數據庫時,執行步驟都是相同的,不同的是每次執行SQL語句。因此,為了簡化數據庫訪問操作、減少代碼冗余、提高效率,需要將訪問數據庫時通用的基礎代碼進行封裝,即程序員自己編寫一個數據庫訪問工具類DBUtil,用於提供訪問數據庫時所用到的連接、查詢、更新和關閉等操作的基本方法,其他類通過調用DBUtil工具類來實現數據庫的訪問。
1. 編寫屬性文件
為了便於后期維護,在編寫DBUtil工具類之前,通常將連接數據庫的參數信息保存在屬性文件中。
- 在項目的根目錄下創建一個config子目錄,並添加一個屬性文件mysql.properties。該文件時以“鍵-值”對形式來保存連接mysql數據庫的配置信息,內容格式如下:
driver = com.mysql.jdbc.Driver url = jdbc:mysql://localhost:3306/CS?useSSL=false user = root pwd = q9a6z3
為了讀取屬性文件中的配置信息,需要編寫一個Config配置類,在該類中通過java.util.Properties類的get()方法來獲取指定“鍵”所對應的“值”
Config.java
package util; import java.io.FileInputStream; import java.util.Properties; public class Config { private static Properties p = null; static { try { p = new Properties(); p.load(new FileInputStream("config/mysql.properties")); } catch(Exception e) { e.printStackTrace(); } } public static String getValue(String key) { return p.get(key).toString(); } }
2. 編寫DBUtil工具類
DBUtil.java
package db; import java.sql.*; import util.Config; public class DBUtil { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; //得到數據庫連接 public Connection getConnection() throws ClassNotFoundException, SQLException,InstantiationException,IllegalAccessException { String driver = Config.getValue("driver"); String url = Config.getValue("url"); String user = Config.getValue("user"); String pwd = Config.getValue("pwd"); try { Class.forName(driver); //指定驅動程序 conn = DriverManager.getConnection(url,user,pwd); return conn; } catch(Exception e) { throw new SQLException("驅動錯誤或鏈接失敗!"); } }
//釋放資源 public void closeAll() { if(rs != null) { try { rs.close(); } catch(SQLException e) { e.printStackTrace(); } } if(pstmt != null) { try { pstmt.close(); } catch(SQLException e) { e.printStackTrace(); } } if(conn != null) { try { conn.close(); } catch(SQLException e) { e.printStackTrace(); } } } //執行SQL語句,可以進行查詢 public ResultSet executeQuery(String preparedSql,String[] param) { try { pstmt = conn.prepareStatement(preparedSql); if(param != null) { for(int i = 0; i < param.length; i++) pstmt.setString(i+1, param[i]); } rs = pstmt.executeQuery(); } catch(SQLException e) { e.printStackTrace(); } return rs; } //執行SQL語句,可以進行增、刪、改的操作,不能執行查詢 public int executeUpdate(String prepareSql,String [] param) { int num = 0; try { pstmt = conn.prepareStatement(prepareSql); if(param != null) { for(int i = 0; i < param.length; i++) pstmt.setString(i+1, param[i]); } num = pstmt.executeUpdate(); } catch(SQLException e) { e.printStackTrace(); } return num; } }
3.使用DBUtil工具類
import java.sql.ResultSet; import db.DBUtil; public class DBDemo { public static void main(String [] args) { String selectSql = "SELECT id,username,password,sex FROM Userdetails"; String insertSql = "INSERT INTO Userdetails(id,username,password,sex) VALUES(?,?,?,?)"; String updateSql = "UPDATE Userdetails SET password = ? WHERE username = ?"; String deleteSql = "DELETE FROM Userdetails WHERE username = ?"; //創建DBUtil對象 DBUtil db = new DBUtil(); try { db.getConnection(); //連接數據庫 //查詢並顯示原來的數據 ResultSet rs = db.executeQuery(selectSql, null); System.out.println("-----------------原來的數據----------------"); while(rs.next()) { System.out.println("行 " + rs.getRow() + ":" + rs.getInt(1) + "\t" + rs.getString(2) + '\t' + rs.getString(3) + '\t' + (rs.getInt(4) == 1 ? "男" : "女")); } System.out.println("----------------------------------------"); //執行添加 int count = db.executeUpdate(insertSql, new String[] {"9","Rose","123456","0"}); System.out.println("添加" + count + "行"); //執行修改 count = db.executeUpdate(updateSql, new String[] {"zs321","zhangsan"}); System.out.println("修改" + count + "行"); //執行刪除 count = db.executeUpdate(deleteSql, new String[] {"Rose"}); System.out.println("刪除" + count + "行"); //查詢並顯示更新后的數據 rs = db.executeQuery(selectSql, null); System.out.println("----------------更新后的數據------------------"); while(rs.next()) { System.out.println("行 " + rs.getRow() + ":" + rs.getInt(1) + "\t" + rs.getString(2) + '\t' + rs.getString(3) + '\t' + (rs.getInt(4) == 1 ? "男" : "女")); } System.out.println("----------------------------------------"); } catch(Exception e) { e.printStackTrace(); } finally { db.closeAll(); } } }
執行結果:
作者:SeanLiao
寫於2018-1-26