Java 學習筆記(16)——Java數據庫操做

數據庫操做是程序設計中十分重要的一個部分,Java內置JDBC來操做數據庫
java

JDBC使用

JDBC——Java Database connecting Java數據庫鏈接;本質上JDBC定義了操做數據庫的一套接口,做爲應用程序的開發人員來講只須要建立接口對應的對象便可,而接口的實現由各個數據庫廠商去完成。要在應用程序中使用JDBC,須要根據數據庫的不一樣導入對應的jar包。sql

使用步驟以下:數據庫

  1. 導入相應jar包
  2. 註冊驅動
  3. 獲取數據庫鏈接對象
  4. 定義sql語句
  5. 獲取執行sql語句的對象
  6. 執行sql並獲取結果集對象
  7. 從結果集中獲取數據
  8. 釋放資源

相關對象的描述

DriverManager

在使用JDBC以前須要先註冊驅動,也就是告訴JDBC,咱們須要導入哪一個jar包,這個工做由DriverManager對象來實現,能夠調用它裏面的方法 registerDriver 來實現,該方法的定義以下:apache

static void registerDriver(Driver driver);

這個方法須要傳入一個driver 對象,driver對象是具體的數據庫廠商來實現,後續相關操做實際上是根據這個driver對象來調用相關代碼,實現同一套接口操做不一樣數據庫數組

咱們查閱相關實現類的代碼以下:函數

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    /**
     * Construct a new driver and register it with DriverManager
     * 
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

在Driver對象中發現,它在靜態代碼塊中執行了registerDriver方法,也就是說咱們只要加載對應的類,類就會自動幫助咱們進行註冊的操做。因此在第一步註冊驅動的代碼中能夠這樣寫:學習

Class.forName("org.mariadb.jdbc.Driver"); //加載對應的Driver類到內存中

Connection對象

註冊了驅動以後就是獲取數據庫的鏈接對象,在DriverManager中使用getConnection方法獲取,它的定義以下:優化

static Connection getConnection(String url); 
static Connection getConnection(String url, Properties info);
static Connection getConnection(String url, String user, String password);

上述3個方法中,經常使用的是第3個,參數分別爲: 鏈接字串、用戶名、密碼
鏈接字串的格式爲: jdbc:數據庫類型://數據庫IP:端口/數據庫名稱,好比 jdbc:mariadb://localhost:3306/testui

獲取鏈接字串的代碼以下:url

Connection conn = DriverManager.getConnection("jdbc:mariadb://localhost:3306/study", "root", "root");

執行sql語句

獲取鏈接對象以後,須要向數據庫傳遞sql語句並執行它,執行sql語句須要使用對象 Statement, 經常使用的方法以下:

boolean execute(String sql);
ResultSet executeQuery(String sql);
int executeUpdate(String sql);

通常可使用execute來執行相關操做,若是是查詢語句,可使用executeQuery來執行並獲取返回的結果集,若是須要執行DELTE、UPDATE、INSERT等語句可使用executeUpdate來更新數據庫

咱們能夠經過 Connection對象的createStatement方法獲取一個Statement對象,代碼以下:

Statement statement = conn.createStatement();
String strSql = "INSERT INTO student VALUES(2, '2b', 28, 78.9, '2017-12-30', NULL)";
statement.execute(strSql);
statement.close(); //最後別忘了關閉對象

獲取返回結果

若是咱們執行了像insert、delete、update等等語句,可能不須要關注具體的返回結果,可是若是使用的是select語句,則須要獲取返回的結果

獲取select語句返回的結果可使用 executeQuery 方法,該方法會返回一個結果集對象

能夠將結果集對象想象成一個二維的數組,保存了查詢到的相關數據,每一行表明一條數據,行中的每一列是一個字段的數據。結果集中使用遊標來遍歷每一行數據。使用get相關函數來獲取對應索引的數據。一行遍歷完了使用next移動到下一行;其中get相關方法主要有:

Blob getBlob(int columnIndex); 
Blob getBlob(String columnLabel);
boolean getBoolean(int columnIndex);
boolean getBoolean(String columnLabel);
byte getByte(int columnIndex); 
byte getByte(String columnLabel);
byte[] getBytes(int columnIndex);
byte[] getBytes(String columnLabel);
Date getDate(int columnIndex); 
Date getDate(int columnIndex, Calendar cal); 
Date getDate(String columnLabel); 
Date getDate(String columnLabel, Calendar cal);
double getDouble(int columnIndex);
double getDouble(String columnLabel);
float getFloat(int columnIndex);
float getFloat(String columnLabel);
int getInt(int columnIndex);
int getInt(String columnLabel);
long getLong(int columnIndex);
long getLong(String columnLabel);

在獲取告終果以後須要關閉對應對象清理資源,這部分只須要調用對應的cloase方法便可

最終一個完整的demo 以下:

public class JDBCDemo1 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            Class.forName("org.mariadb.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mariadb://localhost:3306/test", "root", "root");
            String sql = "select * from student";
            statement = conn.createStatement();
            resultSet = statement.executeQuery(sql);

            while (resultSet.next()){
                int id = resultSet.getInt(1); //注意:這裏面的索引是從1開始的
                String name = resultSet.getString(2);
                int age = resultSet.getInt(3);
                double score = resultSet.getDouble(4);
                Date birthday = resultSet.getDate(5);
                Timestamp insertTime = resultSet.getTimestamp(6);

                System.out.println(id + "\t" + name + "\t" + age + "\t" + score + "\t" + birthday + "\t" + insertTime);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try{
                if (resultSet != null){
                    resultSet.close();
                }

                if (statement != null){
                    statement.close();
                }
                if (conn != null){
                    conn.close();
                }
            }catch (SQLException e){
                e.printStackTrace();
            }
        }

    }
}

參數化查詢

咱們知道使用sql拼接的方式來執行sql語句容易形成sql注入漏洞,即便針對某些關鍵字進行過濾也很難消除這個漏洞,一旦存在sql注入,那麼數據庫中的數據很容易就會被黑客竊取。而使用參數化查詢的方式能夠從根本上消除這個漏洞。

jdbc中參數化查詢使用的對象是 PreparedStatement, 它與Statement對象不一樣在於,它會提早將sql語句進行編譯,後續只會接收固定類型的參數;而Statement只會簡單的去執行用戶輸入的sql語句。

在進行參數化查詢的時候須要先準備sql語句,可是在查詢參數中須要使用 ? 作標記,表示這個位置是一個參數,後續在真正執行前再傳入,好比說能夠準備這樣的sql語句 update student set score = 100 where name = ?

準備好sql語句以後,須要設置對應參數位置的值,咱們可使用 setXxx 方法來設置,setXxx 方法與以前介紹的get方法相似,根據不一樣的數據類型 Xxx 有不一樣的取值。

設置完參數以後,與Statement 同樣,調用對應的execute方法來執行便可.

String sql = "update student set score = 100 where name = ?";
ps = conn.prepareStatement(sql);
ps.setString(1, "2b");
ps.executeUpdate();

數據庫鏈接池

在須要頻繁操做數據庫的應用中,使用數據庫鏈接池技術能夠對數據庫操做進行必定程度的優化。原理請自行百度。

若是要本身實現數據庫鏈接池須要實現 javax.sql.DataSource 的getConnection方法。固然我學習Java只是爲了學習一下Web相關的內容,並不想太過於深刻,因此天然不會去管怎麼實現的,只要調用第三方實現,而後使用就行了。

常見的開源的第三方庫有: Apache commons-dbcp、C3P0 、Apache Tomcat內置的鏈接池(apache dbcp)、druid(由阿里巴巴提供)。

本着支持國產的心態,此次使用的主要是 druid。

druid 鏈接池須要提供一個配置文件來保存數據庫的相關內容

driverClassName=org.mariadb.jdbc.Driver
url=jdbc:mariadb://localhost:3306/study
username=root
password=masimaro_1992
# 初始化時鏈接池中保留鏈接數
initialSize=5
# 最大鏈接數
maxActive=10
# 最大時間,超過這個時間沒有任何操做則會關閉鏈接
maxWait=3000

在使用時主要須要以下步驟:

  1. 加載配置文件
  2. 調用 DruidDataSourceFactory.createDataSource 方法傳入 配置,獲取到 DataSource 對象
  3. 調用DataSource.getConnection 方法獲取Connection 對象
  4. 執行後續操做

相關代碼以下:

Connection conn = null;
Statement statement = null;

Properties properties = new Properties();
try {
    properties.load(JDBCDemo3.class.getResourceAsStream("druid.properties"));
    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
    conn = dataSource.getConnection();
    statement = conn.createStatement(); 

    //do something
} catch (IOException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}
相關文章
相關標籤/搜索