使用JDBC操作MySQL數據庫

JDBC(Java Database Connectivity,Java數據庫連接)是一種用於連接多種數據庫的標準工具,使Java語言通過該接口可以連接到Oracle、MySQL,SQL server等多種不同數據庫。

1、使用步驟

1、導入JDBC驅動

在Java中使用jdbc連接MySQL數據庫需要導入jdbc驅動,從MySQL官網https://dev.mysql.com/downloads/connector/j/下載驅動如下:

解壓zip文件得到mysql-connector-java的jar文件,將該文件粘貼到項目的lib文件夾下,並將lib文件添加到依賴(在IDEA中右擊lib文件夾,選擇Add as Library)。也可以將jar包粘貼到lib目錄下,然後右鍵選擇Add as Library,添加到項目依賴,添加之後文件左側會有一個箭頭

2、連接MySQL

接下來在代碼中使用jdbc連接數據庫並獲取student表中的內容:

import java.sql.*;

public class MysqlConnector {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
        String user="root";
        String password="123456";
        Connection connection= null;
        Statement statement=null;
        ResultSet res=null;
        try {
            //1、註冊驅動
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2、獲取連接對象
            connection = DriverManager.getConnection(url,user,password);
            //3、創建statement對象
            statement=connection.createStatement();
            //4、執行SQL語句
            String sql="select * from student";
            ResultSet res=statement.executeQuery(sql);
            //5、處理結果集
            while(res.next()) {
                String name=res.getString("Name");
                int age=res.getInt("Age");
                System.out.println("姓名:"+name+",年齡:"+age);
            }
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            //6、釋放資源
            try {
                res.close();
                statement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }            
        }
    }
}

其中在獲取connection對象時要傳入url、用戶名和密碼三個參數,例如:url爲jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai,其中jdbc爲固定,mysql要連接數據庫名稱,localhost:3306爲數據庫的地址和端口號,test爲選擇其中的Database數據庫名,?後面爲指定的連接參數,這裏對連接的時區進行了設置,還可以指定字符集、編碼方式等。

如果執行數據庫增刪改操作,使用execute()方法,如果執行查詢操作,使用executeQuery(),並且會返回一個結果集對象ResultSet

結果集的next()方法可以將光標移動到下一條記錄,在每條記錄中可以通過getXxx("fieldname")方法獲取對應l類型的數據,括號中傳入字段名作爲參數。

3、通過預處理防注入

由於數據庫在查詢時可能收到注入攻擊,可以通過預處理對象來執行數據庫語句防止注入攻擊。首先在sql語句中將需要查詢的參數用佔位符?代替,之後創建PreparedStatement對象,在利用setXxx()方法將參數傳入,最後再執行即可。

//利用?填充並創建Preparedstatement對象
String sql="select * from student where name=? and password=?";
PreparedStatement pst=conn.prepareStatement(sql);
//得到用戶輸入的查詢內容並填充到statement
String name=scanner.next();
String pwd=scanner.next();
pst.setString(1, name);    // 將name變量填充到第1個?的位置
pst.setString(2, pwd);
//執行sql語句並得到結果集
ResultSet res= pst.executeQuery();

2、調用存儲過程

MySQL數據中可以把常用的操作定義爲存儲過程,這樣可以更加方便地執行一些常用sql語句。

存儲操作過程可以傳入參數(入參),也可以將返回的結果當作參數傳出(出參),如下所示創建一個帶入參的存儲過程

CREATE PROCEDURE sp_query_name(IN sp_id INT)
BEGIN
   IF sp_id = 0 THEN
       SELECT * FROM student;
   ELSE
       SELECT * FROM student WHERE id=sp_id;
   END IF;
END;

直接在控制檯調用該過程:CALL sp_query_name(1001);

通過jdbc調用時創建CallableStatement對象執行sql語句並獲取查詢結果集

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1、獲取連接對象
        Class.forName("com.mysql.jdbc.Driver");
        String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
        String user="root";
        String password="123456";
        Connection connection= DriverManager.getConnection(url,user,password);
        //2、創建CallableStatement對象
        CallableStatement callableStatement=connection.prepareCall("call sp_query_name(?)");
        //3、傳入參數並執行存儲過程
        callableStatement.setInt(1,0);
        callableStatement.execute();
        //4、獲取結果集並顯示
        ResultSet res=callableStatement.getResultSet();
        while (res.next()){
            String name=res.getString("Name");
            int age=res.getInt("Age");
            System.out.println("姓名:"+name+",年齡:"+age);
        }
    }

出參存儲過程將結果保存在傳入的參數中返回,例如統計student表中學生數量,將結果保存在傳入變量num中

#創建存儲過程
CREATE PROCEDURE sp_count(OUT num INT)
BEGIN
    SELECT count(*) INTO num FROM student;
END;

#調用出參過程並顯示參數值
call sp_count(@stu_num);
select @stu_num;

通過JDBC調用存儲過程如下,不同的是調用時不傳入參數,而是註冊參數的類型,然後在執行結束後通過getXxx()獲取返回的傳出參數

        //1、獲取連接對象
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
        String user = "root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url, user, password);
        //2、創建CallableStatement對象
        CallableStatement callableStatement = connection.prepareCall("call sp_count(?)");
        //3、註冊參數並執行
        callableStatement.registerOutParameter(1, Types.INTEGER);
        callableStatement.execute();
        //4、獲取傳出參數
        int studentNum = callableStatement.getInt(1);     
        System.out.println("學生人數:" + studentNum);

3、使用事務

數據庫的事務(Transaction)是作爲單個邏輯單元執行的一系列操作,這些操作作爲一個整體向系統提交,要麼都執行,要麼都不執行。事務具有原子性、一致性、隔離性(併發事務隔離互斥訪問)、永久性(對數據庫內容永久地修改)。

例如在一個銀行轉賬過程,賬戶A將100元轉給賬戶B,需要將賬戶A-100並且將賬戶B+100,如果在賬戶A-100之後出錯,那麼賬戶B沒有增加,這100元就憑空消失了。因此這兩個步驟需要作爲一個整體來執行。首先需要將數據庫的自動提交關閉,在執行相關操作之後再手動提交事務,反之如果執行過程中出錯,則需要回滾事務,撤銷之前的操作。

connection.setAutoCommit(false);    //關閉自動提交
try{                            //執行一個完整的事務操作
    //賬戶A-100
    //賬戶B+100
    connection.commit();    //提交事務
}catch(Exception e){            //如果在執行中報錯
    connection.rollback();    //回滾事務
}

4、JDBC連接池

之前採用的數據庫連接方式都是使用JDBC直接連接MySQL的,如果建立的連接數量過多會導致數據庫崩潰,因此可以採用連接池來管理與數據庫之間的連接數量。當一個連接請求到達時,從連接池中取出一個連接,當連接數量過多連接池中的連接分配完時,其他新到達的連接請求則需要等待。常用的兩個連接池爲dbcp和c3p0。

使用dbcp首先需要導入相關jar包,並且需要在項目根目錄下增加配置文件,通過apache官網下載dbcp所需的jar包,將下載後的內容解壓到項目lib文件夾下

dbcp.jar:http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
logging.jar:http://commons.apache.org/proper/commons-logging/download_logging.cgi
pool.jar:http://commons.apache.org/proper/commons-pool/download_pool.cgi

在項目目錄下新建resources/dbcp.properties文件用於保存dbcp的相關配置,其內容如下:

#驅動類名
driverClassName=com.mysql.jdbc.Driver
#連接到的數據庫url
url=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai
#用戶名
username=root
#密碼
password=123456
#線程池同一時間分配最大連接數,如果爲負數,代表不限制
maxActive=30
#線程池中允許最大的保持空閒連接數量,超過的將被釋放
maxIdle=10
#最大等待時間,等待連接池的最長時間,超出則拋出異常
maxWait=1000
#連接池啓動時創建的鏈接數
initialSize=1

新建一個DbcpUtils工具類,並通過getConnection()返回Dbcp的連接對象

public class DbcpUtils {
    private static DataSource DS;
    private static final String configFile = "resources/dbcp.properties";

    //構造方法中初始化DBCP數據源
    public DbcpUtils() throws Exception {
        //讀取properties文件
        Properties properties = new Properties();
        FileInputStream inputStream = new FileInputStream(configFile);
        properties.load(inputStream);
        //創建數據源
        DS = BasicDataSourceFactory.createDataSource(properties);
    }

    //返回連接對象
    public Connection getConnection() {
        Connection con = null;
        try {
            con = DS.getConnection();
            con.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }
}

在主函數中測試Dbcp,通過調用getConnection()得到一個Connection對象,之後就正常操作數據庫一樣了

    public static void main(String[] args) throws Exception {
        //新建Dbcp對象並返回一個連接對象
        DbcpUtils db=new DbcpUtils();
        Connection con=db.getConnection();
        //執行SQL操作並查看結果
        Statement statement=con.createStatement();
        String sql="select * from student";
        ResultSet res=statement.executeQuery(sql);
        while(res.next()) {
            String name=res.getString("Name");
            int age=res.getInt("Age");
            System.out.println("姓名:"+name+",年齡:"+age);
        }
    }

同理使用c3p0也需要先導入兩個jar包

c3p0:https://www.mvnjar.com/com.mchange/c3p0/0.9.5.1/detail.html

mchange-commons:https://www.mvnjar.com/com.mchange/mchange-commons-java/0.2.16/detail.html

然後在resources下創建c3p0.properties文件

c3p0.driverClass = com.mysql.jdbc.Driver
c3p0.jdbcUrl = jdbc:mysql://localhost:3306/test
c3p0.user = root
c3p0.password = 123456
c3p0.maxPoolSize = 20
c3p0.minPoolSize = 3
c3p0.maxStatements = 30
c3p0.maxIdleTime = 150

最後與dbcp不同的是,c3p0將讀取properties文件、構建數據源等操作已經封裝好了,可以直接構建並獲得connection對象

        //直接創建c3p0的數據源並調用getConnection()
        ComboPooledDataSource c3Source=new ComboPooledDataSource();
        Connection con=c3Source.getConnection();
        //執行SQL操作並查看結果
        Statement statement=con.createStatement();
        ......

 

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