1. 程式人生 > 實用技巧 >Java進階之JDBC

Java進階之JDBC

Java進階之JDBC

Java進階之JDBC

什麼是JDBC

  • 它是Java操作資料庫的一組介面
  • 它也是資料庫開發的規範
    • 針對程式開發人員的規範
    • 針對於資料庫廠商的規範

操作JDBC

    • 下載JDBC
    • 在專案中匯入下載的jar包
    • Java操作MySQL基本步驟
      • 載入驅動,預設情況下,Java程式中是沒有JDBC的,需要在程式啟動時,將JDBC載入到Java程式中後,即可在程式中使用JDBC
        • Class.forName("com.mysql.jdbc.Driver")
      • 連線資料庫
        • 使用驅動管理器連線資料庫 DriverManager.getConnection(URL,USER,PASSWORD)
        • 如果連線成功後返回資料庫連線物件Connection,是Java程式與資料庫進行通訊的橋樑
        • 一定要使用java.sql下的Connection
      • 操作資料庫
        • 使用Statement介面進行資料庫操作
        • Statement介面的來源必須是由Connection物件建立
      • 釋放資源
        • close關閉連線
        • 一般建立物件放置在異常塊外部,在finally釋放資源時,丟擲空指標異常
      • 一些常見問題
        • 建立的類名稱不要和API庫名稱一樣
        • 保證MySQL資料庫的版本與JDBC的版本要一致,否則會報出異常,比如時區異常,檢查性異常
import java.io.*;
import java.sql.*;

public class JDBC { /** * 導包 mysql-connector-java-5.1.34-bin * @珍珠奶茶不加糖 */ //靜態內部類載入驅動 static{ //處理類載入異常 try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
//建立連線 public void JDBC(){ //從檔案中讀取URL,USER,PASSWORD File file = new File("E:\\JAVA\\Java2006\\src\\com\\xumouren\\work0823\\jdbc.txt"); FileReader fileReader = null; BufferedReader bufferedReader = null; String URL = null; String USER = null; String PASSWORD = null; try { fileReader = new FileReader(file);//拋檔案處理異常 bufferedReader = new BufferedReader(fileReader); URL = bufferedReader.readLine();//拋IO流異常 USER = bufferedReader.readLine(); PASSWORD = bufferedReader.readLine(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally {//關閉連線 if(bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if(fileReader!=null){ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } //連線資料庫 Connection connection = null; Statement statement = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; //拋資料庫異常 try { connection = DriverManager.getConnection(URL,USER,PASSWORD); if(connection.getAutoCommit()){//關閉資料庫自動提交 connection.setAutoCommit(false); } } catch (SQLException e) { e.printStackTrace(); } try { //使用sql語句兩種方式 //方式一 String sql1 = "insert EMP values(7000,'張三','寫bug',7839,null,2000,null,10)"; statement = connection.createStatement(); statement.execute(sql1); //方式二 -- 預編譯形式 String sql2 = "select * from EMP where ENAME = ? "; preparedStatement = connection.prepareStatement(sql2); //將所要求的值傳入問號處 preparedStatement.setObject(1,"張三"); //將查詢結果按結果集輸出 //查詢用executeQuery(); 修改改用executeUpdate(); excute()可以執行所有的SQL語句 resultSet = preparedStatement.executeQuery(); while(resultSet.next()){//迭代輸出 String ename = resultSet.getString("ENAME"); int empno = resultSet.getInt("EMPNO"); // 變數[型別與後面資料庫資料型別對應] = resultSet.get[資料庫資料型別](欄位名); System.out.println(ename+empno);//輸出結果 } //如果上述都沒有異常,則提交 connection.commit(); } catch (SQLException e) { //如果出現異常,則回滾 try { connection.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); }finally {//關閉連線 if(resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(preparedStatement!=null){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(statement !=null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } //入口 public static void main(String[] args) { JDBC jdbc = new JDBC(); jdbc.JDBC(); } }

    • JDBC核心介面
      • Connection
        • 與資料庫進行連線
        • 作用:與資料庫進行互動
        • 常用的API方法
          • DriverManager.getConnection(url,user,password)
          • 對資料庫進行事務操作
          • SetAutoCommit(boolean)
      • Statement
        • 實現在Java中執行SQL語句
        • 通過excute(sql)方法,將指定的SQL傳入到MySQL資料庫中執行
        • 執行excute有三種形式
          • excute(sql) -- 執行所有的sql命令
          • excuteQuery(sql) -- 此方法只能執行對MySQL進行查詢的命令
          • excuteUpdate(sql) -- 此方法只能執行對MySQL修改的命令
        • 返回值
          • 當執行select命令後,所有的資料將封裝的物件(ResultSet)返回給Java程式
          • 返回的是資料表的快照,返回到記憶體中
        • 子介面PreparedStatement
          • 出現子介面原因
          • 因為在使用Statement執行查詢的時候,會出現SQL注入問題
          • 什麼是SQL注入
            • 破壞原有的SQL語句結構,新增新的SQL指令
            • 使原有SQL失去效果
          • PreparedStatement預編譯
            • 防止SQL注入
            • 執行SQL命令時,資料的組裝更簡單
            • 預編譯會使執行效率更高
      • ResultSet
        • 該介面是MySQL資料查詢後,返回的資料記錄集
        • 此介面預設指向記憶體表中第一行資料的上面
        • 此介面的方法可以實現訪問記憶體表
        • 所有的資料都儲存到ResultSet物件
        • 常用API
          • next() -- 可以判斷下一行有沒有資料,返回值型別Boolean
          • get()<'Type'>(int) -- 引數int表示列的序號,通過列的序號來獲取當前資料
          • get()<'Type'>(String) -- 引數String表示列的名稱,通過列的名稱來獲取資料
    • 操作日期型別資料
      • 在MySQL資料庫中,常用日期的型別
        • date
        • datetime
        • year
        • timestamp
      • 使用java.sql包下時間類
        • 繼承自java.util.Date下
    • 操作事務
      • 關閉自動提交SetAutoCommit(boolean)
      • 提交commit
      • 回滾rollback
    • JDBC操作大物件
      • 將大物件資料按照二進位制通過流的方式寫入
      • 例如儲存一張圖片
        • 方法一:將圖片上傳到伺服器本地,在資料庫中存放圖片的路徑
        • 方法二:將圖片通過流按照二進位制方式存放進資料庫
      • 在MySQL中,操作大物件的資料型別有兩種
        • text -- 針對文字的大物件型別
        • blob -- 針對於二進位制的大物件型別
      • JDBC操作blob步驟
        • 寫操作
        • 使用Connection物件建立blob物件
        • Blob blob = connection.createBlob()
        • 將要儲存搭配資料庫的二進位制資料寫入搭配blob物件中
          • 需要使用blob物件中提供的輸出流物件,向blob物件儲存二進位制資料
          • 向blob物件中的指定位置,一般都是從頭開始寫入,設定引數為1
          • 使用OutputStream中的Write()方法向blob物件輸出資料
          • 使用preparedStatament將blob物件執行到MySQL資料庫
        • 讀取與寫入操作相反
import java.io.*;
import java.sql.*;

public class TestBlob {
    static {//載入驅動
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        String url = null;
        String user = null;
        String password = null;
        try {
            Connection connection = DriverManager.getConnection(url,user,password);
            //建立檔案流
            File file = new File("E:\\img\\圖片一.jpg");
            //讀取檔案
            FileInputStream fileInputStream = new FileInputStream(file);

            //建立Blob物件,用來儲存二進位制資料
            Blob blob = connection.createBlob();
            
            //建立輸出流,用來將二進位制資料儲存到Blob物件中
            OutputStream outputStream = blob.setBinaryStream(1);
            
            //建立位元組陣列
            byte[] bytes = new byte[100];
            //檢測是否讀取到資料
            int size = -1;
            //將讀取到的值存入bytes,返回儲存字元個數
            while((size = fileInputStream.read(bytes))!=-1){
                outputStream.write(bytes,0,size);//將位元組寫入,從0開始,到最後一個
            }
            outputStream.close();//關閉流
            fileInputStream.close();
            String sql = "insert img values(?,?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"圖片一.jpg");
            preparedStatement.setBlob(2,blob);
            preparedStatement.close();
            connection.close();
            
        } catch (SQLException e) {
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

    • 元資料
      • 元資料是用來描述資料的資料
      • 主要用來說明“資料”的意義
      • 元資料的分類
        • 資料庫“元資料”
          • 資料庫的元資料體現了資料庫相關的資訊
          • 包含資料庫的版本、驅動名稱等等
          • 通過Connection下的getMetaData()獲取元資料資訊
          • 資料庫元資料儲存到返回的Database物件中

      • 資料表“元資料”
        • 主要是用來描述表的資訊的
        • 資料表元資料與資料無關
        • 常用API
          • 獲取資料表列的總數 -- getColumnCount
          • 獲取資料表列的原名稱 -- getColumnName
          • 獲取資料表列的別名 -- getColumnLable 沒有別名則獲取原名稱
          • 獲取資料表列的型別對應的常量值 -- getColumnType
          • 獲取資料表列的型別名稱 -- getColumnTypeName
  • JDBC主鍵返回與批量新增
    • 主鍵資料的自動返回
      • 使用主鍵資料自動返回,會自動返回主鍵值,可以省去一步查詢過程
      • 使用主鍵自動返回操作
        • 建立PreparedStatement時,要指定是否自動返回主鍵
        • PreparedStatement preparedStatement = connection.preparedStatement(sql,[1 | PreparedStatement.RETURN_GENERATED_KEYS])
        • 如果輸入2,或NOT_RETURN_GENERATED_KEYS則不返回
        • 使用preparedStatement.getGeneratedKeys獲取主鍵,返回一個ResultSet
    • 批量新增
      • 執行批量命令與執行單條命令是不一樣的
      • 將待插入的資料儲存到快取中 -- preparedStatement.addBatch()
      • 批量執行,將快取中每一條記錄迴圈插入到資料表中 -- preparedStatement.excuteBatch()

import java.io.*;import java.sql.*;
public class TestBlob { static {//載入驅動 try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static void main(String[] args) { String url = null; String user = null; String password = null; try { Connection connection = DriverManager.getConnection(url,user,password); //建立檔案流 File file = new File("E:\\img\\圖片一.jpg"); //讀取檔案 FileInputStream fileInputStream = new FileInputStream(file);
//建立Blob物件,用來儲存二進位制資料 Blob blob = connection.createBlob(); //建立輸出流,用來將二進位制資料儲存到Blob物件中 OutputStream outputStream = blob.setBinaryStream(1); //建立位元組陣列 byte[] bytes = new byte[100]; //檢測是否讀取到資料 int size = -1; //將讀取到的值存入bytes,返回儲存字元個數 while((size = fileInputStream.read(bytes))!=-1){ outputStream.write(bytes,0,size);//將位元組寫入,從0開始,到最後一個 } outputStream.close();//關閉流 fileInputStream.close(); String sql = "insert img values(?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,"圖片一.jpg"); preparedStatement.setBlob(2,blob); preparedStatement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); }catch (IOException e){ e.printStackTrace(); } }}