調用JDBC執行sql操作

JDBC(Java Data Base Connectivity,java數據庫連接)是一種用於執行SQL語句的Java API,可以爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC提供了一種基準,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序。簡言之,JDBC就是Java用於執行SQL語句實現數據庫操作的API。

使用JDBC的大體步驟是這樣的:

1.註冊數據庫驅動

通常使用 Class.forName() 的方式進行註冊.不同數據庫驅動不同,本例採用的是 mysql 驅動.下面介紹了兩種數據庫對應的驅動樣式.

RDBMS JDBC驅動名稱 URL格式
MySQL com.mysql.jdbc.Driver jdbc:mysql://hostName/databaseName
ORACLE oracle.jdbc.driver.OracleDriver jdbc:oracle:thin:@hostName:portNumber:databaseName
Calss.forName("JDBC驅動名稱")

2.獲取數據庫鏈接

Connection connection = DriverManager.getConnection();

方法參數可選,不過最終都是調用的此方法

 private static Connection getConnection(
        String url, java.util.Properties info, Class<?> caller) throws SQLException{
        ...
}

3.創建發送sql語句對象

可以根據需求選擇創建三種對象:  Statement,PreparedStatement,CallableStatement,三者關係爲

Statment 接口提供了執行語句和獲取結果的基本方法,支持普通的不帶參數的sql語句,批量更新、刪除等操作。每次使用都需要重新載入sql語句。

PreparedStatement 爲 Statment 子接口,添加了 IN 參數的處理方法,支持可變參數sql,採用預編譯處理,編譯一次,執行多次,較Statment 接口而言,效率大大提高,而且也可以有效的防止sql注入問題。

CallableStatement 爲 PreparedStatement 子接口,添加了 OUT , INOUT 參數的處理方法,支持調用存儲過程。

4.發送sql語句

發送sql語句方法以及設置動態參數方法很多,建議閱讀源碼.這裏介紹三種發送sql語句方法:

executeQuery() 用於發送查詢語句

executeUpdate() 用於發送增添,修改,刪除語句

execute() 用於發送所有語句

5.釋放資源


 

接下來進行詳細的演示

一、配置文件 jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.20.103:3306/my_test
user=root
password=123456

編寫配置文件的目的是數據庫有修改時只需修改配置文件,編寫的工具類不需要改動.也可以省略此步驟,在工具類內部直接使用數據庫的基本配置.

二、JDBC工具類

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @author YoonaLt
 * @date 2019/11/1
 * jdbc工具類
 */
public class JdbcUtils {

    /**
     * 獲取數據庫鏈接
     *
     * @return mysql鏈接對象
     */
    public static Connection getConnection() {
        // 獲取此類的類加載器
        ClassLoader classLoader = JdbcUtils.class.getClassLoader();
        // 獲取配置文件的輸入流
        InputStream inputStream = classLoader.getResourceAsStream("jdbc.properties");
        // 配置工具
        Properties properties = new Properties();
        // 加載
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 從配置文件讀取需要的配置屬性
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        // 加載數據庫驅動
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 獲取數據庫鏈接
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 釋放資源
     *
     * @param connection 鏈接對象
     * @param statement  發送sql語句對象
     * @param resultSet  返回對象集合
     */
    public static void release(Connection connection, Statement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.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();
            }
        }
    }
}

三、測試

1.建表

public static void createTable() {
        // 獲取數據庫鏈接
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = null;
        String sql = "create table user(id int auto_increment primary key,name varchar(50) comment '姓名'," +
                "sex tinyint comment '0男,1女',birthday datetime comment '生日',profession varchar(20) comment '職業')" +
                "default charset=utf8;";
        try {
            // 創建向數據庫發送sql語句對象
            ps = connection.prepareStatement(sql);
            // 發送sql語句
            ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 釋放資源
            JdbcUtils.release(connection, ps, null);
        }
    }

2.插入數據

    public static void insert() {

        LocalDateTime localDateTime = LocalDateTime.of(1990, 5, 30, 12, 50, 40);
        long l = localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Date dateYoona = new Date(l);
        Date dateIU = Date.valueOf("1993-05-16");

        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = null;
        // 可以直接填寫完整的sql語句,也可以使用佔位符.
        String sql = " insert into user(name,sex,birthday,profession) values ('IU',1,?,'idol'),('Yoona',1,?,'idol')";
        try {
            ps = connection.prepareStatement(sql);
            // 使用佔位符時,最好使用佔位類型對應的設置方法.也可都使用setObject()方法,第一個參數爲佔位符位置,從 1 開始,第二個爲替換值
            ps.setDate(1, dateIU);
            ps.setObject(2, dateYoona);
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(connection, ps, null);
        }
    }

3.查詢數據

(1)返回的數據確定只有一條

public static void select() {

        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = null;
        // 查詢返回結果集
        ResultSet resultSet = null;
        String sql = "select * from user where name = ?";
        try {
            ps = connection.prepareStatement(sql);
            ps.setString(1, "Yoona");
            resultSet = ps.executeQuery();
            if (resultSet.next()) {
                System.out.println(resultSet.getString("name"));
                System.out.println(resultSet.getInt("sex"));
                System.out.println(resultSet.getDate("birthday"));
                System.out.println(resultSet.getString("profession"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(connection, ps, resultSet);
        }
    }

(2) 返回的結果可能是多條

    public static void selectMany() {
        List<Map<String, String>> list = new ArrayList();
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement cs = null;
        ResultSet resultSet = null;
        String sql = "select * from user";
        try {
            cs = connection.prepareStatement(sql);
            resultSet = cs.executeQuery();
            // 使用while
            while (resultSet.next()) {
                Map<String, String> m = new HashMap(16);
                m.put("name", resultSet.getString("name"));
                m.put("profession", resultSet.getString("profession"));
                list.add(m);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(connection, cs, resultSet);
        }
        // 打印驗證是否成功取出多條數據
        list.forEach(map -> System.out.println(map.get("name") + " 的職業是 " + map.get("profession")));
    }

使用 while 循環,將每一個返回集放入準備好的容器中

4.事務

在jdbc中處理事務,是通過使用同一個 Connection 來實現的.

setAutoCommit(boolean autoCommit),設置是否自動提交事務,默認爲 true,如果設置爲false,則代表開啓事務

commit() ,提交事務

rollback(),回滾

 public static void commit() {
        Connection c = JdbcUtils.getConnection();
        PreparedStatement ps = null;
        try {
            // 開啓事務
            c.setAutoCommit(false);
            // 設置主鍵衝突,觸發事務
            String sqlOne = " insert into user(id,name,sex,profession) values (1,'Yoona',1,'idol')";
            ps = c.prepareStatement(sqlOne);
            ps.executeUpdate();
            String sqlTwo = " insert into user(id,name,sex,profession) values (1,'IU',1,'idol')";
            ps = c.prepareStatement(sqlTwo);
            ps.executeUpdate();
            // 提交事務
            c.commit();
        } catch (SQLException e) {
            try {
                // 發生異常即回滾
                c.rollback();
                System.out.println("----------回滾----------");
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JdbcUtils.release(c, ps, null);
        }
    }

項目使用的框架對JDBC 已經封裝的十分好了,不過適當的瞭解JDBC的工作步驟還是有助於對框架的理解的.由於本人水平有限,難免出現錯誤與遺漏,歡迎指正.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章