1. 程式人生 > >JDBC詳解之與mySQL資料庫的連線和基本操作一

JDBC詳解之與mySQL資料庫的連線和基本操作一

JDBC詳解


一 JDBC基本操作

MySQL的JDBC驅動包: mysql-connector-java-5.1.38-bin.jar

  • mysql-connector-java-5.1.38-bin.jar
    是MySQL的JDBC驅動包,用JDBC連線MySQL資料庫時必須使用該jar包。
  • maven
<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
  • 1 載入驅動
  • 2 獲得連線
  • 3 基本操作,執行SQL語句
  • 4 遍歷結果集
  • 5 釋放資源

程式碼如下

        //1 載入驅動
        Class.forName("com.mysql.jdbc.Driver");
        //2 獲得連線
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/han","root","123");
        //3 基本操作,執行SQL
        //3.1 獲得執行SQL語句的物件
        Statement createStatement = conn.createStatement();
        //3.2 編寫SQL語句
        String sql = "select * from orderitem";
        //3.3 執行SQL
        ResultSet resultSet = createStatement.executeQuery(sql);
        //3.4 遍歷結果集
        while(resultSet.next()){
            System.out.println(resultSet.getInt("id"));
            System.out.println(resultSet.getString("product"));
            System.out.println(resultSet.getDouble("price"));
        }
        //4. 釋放資源
        resultSet.close();
        createStatement.close();
        conn.close();
    }

物件詳解:

  • DriverManager:驅動管理類

    • 作用 1 : 註冊驅動. 實際開發中一般不會使用,它會導致驅動註冊兩次
    • 作用 2 : 獲得連線
    • getConnection: 用來獲得與資料庫連線的方法:這個方法中有三個引數:
               url         :與資料庫連線的路徑
               user            :與資料庫連線的使用者名稱
               password        :與資料庫連線的密碼
    
    • 主要關注的是url的寫法:
    jdbc:mysql://localhost:3306/web_test3
               jdbc        :連線資料庫的協議
               mysql       :是jdbc的子協議
               localhost   :連線的MySQL資料庫伺服器的主機地址。(連線是本機就可以寫成localhost),如果連線不是本機的,就需要寫上連線主機的IP地址。
               3306        :MySQL資料庫伺服器的埠號
               web_test3   :資料庫名稱
            url如果連線的是本機的路徑,可以簡化為如下格式:
            jdbc:mysql:///web_test3
    
    • connection : 資料庫連線物件

      • 作用 1 建立執行SQL語句的物件
      • 作用 2 管理事務
    • statement ; 執行SQL

      • 執行SQL
      • 批處理
    • ResultSet :結果集
      • 通過SQL語句查詢的結果

JDBC的增刪改查就不多說了,都是最基本的東西
我們來看一下工具類的抽取和配置檔案的設定

    -

工具類

public class JDBCUtils {

    private static final String driverClassName;
    private static final String url;
    private static final String username;
    private static final String password;

    // 靜態程式碼塊,隨著類的載入二載入
    static {
        // 獲取屬性檔案中的內容
        Properties pro = new Properties();

        try {
            pro.load(new FileInputStream("src/db.properties"));

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        driverClassName = pro.getProperty("driverClassName");
        url = pro.getProperty("url");
        username = pro.getProperty("username");
        password = pro.getProperty("password");
    }

    /**
     * 註冊驅動
     * @throws ClassNotFoundException 
     */
    public static void loadDriver() throws ClassNotFoundException{

        Class.forName(driverClassName);

    }

    /**
     * 獲得連線
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException{

        return DriverManager.getConnection(url,username,password);

    }

    /**
     * 釋放資源的方法
     */
    public static void release(Statement stmt,Connection conn){
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

            stmt = null;
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }
    /**
     * 釋放資源
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void release(ResultSet rs,Statement stmt,Connection conn){
        // 資源釋放:
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

            rs = null;
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

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

}   

配置檔案 db.properties :

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/han
username=root
password=123

二 c3p0連線池

連線池是裝有連線的容器,使用連線的話,可以從連線池中進行獲取,使用完成之後將連線歸還給連線池。

為什麼要使用連線池:

連線物件建立和銷燬是需要耗費時間的,在伺服器初始化的時候就初始化一些連線。把這些連線放入到記憶體中,使用的時候可以從記憶體中獲取,使用完成之後將連線放入連線池中。從記憶體中獲取和歸還的效率要遠遠高於建立和銷燬的效率。(提升效能)。

這裡我們使用c3p0連線池 :

c3p0是一個開源的JDBC連線池.它實現了資料來源和JNDI的繫結,支援JDBC3規範和JDBC2的標準擴充套件.

c3p0 需要引入的jar包:

c3p0-0.9.1.2.jar

  • maven
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

使用連線池查詢資料:

public class C3p0Demo1 {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            //1 建立池
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            //2 設定連線資料庫的引數
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/han");
            dataSource.setUser("root");
            dataSource.setPassword("123");
            //3 獲得連線
            conn = dataSource.getConnection();
            //4 編寫SQL
            String sql = "select * from orderitem";
            //5 預編譯sql
            ps = conn.prepareStatement(sql);
            //6 執行sql
            rs = ps.executeQuery();

            while(rs.next()){
                System.out.println(rs.getInt("id"));
                System.out.println(rs.getString("product"));
                System.out.println(rs.getDouble("price"));
            }
            //4. 釋放資源
            JDBCUtils.release(rs, ps, conn);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

c3p0的配置檔案c3p0-config.xml

c3p0可以使用出c3p0-config.xml檔案配置,也可以使用 .properties檔案配置
建立連線池時預設去類的路徑下查詢一個名字叫 c3p0-config.xml 的檔案.

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql:///han</property>
        <property name="user">root</property>
        <property name="password">123</property>

        <!-- 預設初始化的連線數量,往連線池放5個連線-->
        <property name="initialPoolSize">5</property>
        <!--連線的最少數量-->
        <property name="minPoolSize">5</property>
        <!--連線的最大數量-->
        <property name="maxPoolSize">20</property>
    </default-config> 

    <!-- This app is massive! -->
<!--    <named-config name="oracle">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql:///han</property>
        <property name="user">root</property>
        <property name="password">123</property>
    </named-config> -->
</c3p0-config>
  • 連線池物件應該是一個應用只建立一次就可以的,不需要每次使用都建立一個新的連線池。所以我們要改寫工具類:
public class JDBCUtils2 {
    //獲得連線池
    private static final ComboPooledDataSource dataSource = new ComboPooledDataSource();

    /**
     * 返回連線池
     */
    public static DataSource getDataSource(){

        return dataSource;
    }
    /**
     * 獲得連線
     * @throws SQLException 
     */
    public static Connection getConnection() throws Exception{

        return dataSource.getConnection();
    }

    /**
     * 釋放資源的方法
     */
    public static void release(Statement stmt,Connection conn){
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

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

    public static void release(ResultSet rs,Statement stmt,Connection conn){
        // 資源釋放:
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

            rs = null;
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

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

三 JDBC的工具類庫: DBUtils的概述

開源工具類庫: 對JDBC的簡單封裝,而且沒有影響效能。 因為JDBC手寫比較麻煩,而且有非常多的程式碼是類似的。比如獲得連線,預編譯SQL,釋放資源等..那麼可以將這些程式碼抽取出來放到工具類中。將類似的程式碼進行抽取。大大簡化JDBC的程式設計。

DBUtils需要使用的jar包:**

commons-dbutils-1.6.jar

maven

<!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
<dependency>
    <groupId>commons-dbutils</groupId>
    <artifactId>commons-dbutils</artifactId>
    <version>1.6</version>
</dependency>

DBUtils的API詳解:

  • QueryRunner物件:核心執行類
    • 在一般情況下如果執行CRUD的操作:
      • 構造:
        QueryRunner(DataSource ds);
      • 方法:
        int update(String sql,Object… args);
        T query(String sql,ResultSetHandler rsh,Object… args);
    • 如果有事務管理的話使用另一套完成CRUD的操作
      • 構造:
        QueryRunner();
      • 方法:
        int update(Connection conn,String sql,Object… args);
        T query(Connection conn,String sql,ResultSetHandler rsh,Object… args);

增刪改:

匯入jar包,配置出c3p0-config.xml, JDBCUtils2工具類
這裡不需要手動的釋放資源,DBUtils會自動的釋放資源,則JDBCUtils2工具類中的釋放資源的程式碼就可以刪掉了.
這裡只寫一個插入資料:

    //插入資料
    public void insertProduct() throws SQLException{
        QueryRunner queryRunner = new QueryRunner(JDBCUtils2.getDataSource());
        queryRunner.update("insert into orderitem values (?,?,?)",null,"電視","45.2");
    }

查詢

建立JavaBean :Student 類
處理結果集介面 ResultSetHandler 的實現類:

  • BeanHandler : 將一條記錄封裝到javaBean中去 行 (常用)
        @Test
        public void demo1() throws SQLException{
            QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
            Student student = qr.query(" select * from user where id = ?",new BeanHandler<Student>(Student.class),2 );
            System.out.println(student);
        }
  • BeanListHandler : 將多條記錄封裝到裝有javaBean的List集合中去 行(常用)
                @Test
                /**
                 * 一條記錄就是一個Java物件(javaBean),如果多條記錄,則將多個物件裝到List集合中去.
                 * @throws SQLException
                 */
                public void demo2() throws SQLException{
                    QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
                    List<Student> list = qr.query("select * from user ", new BeanListHandler<Student>(Student.class));
                    for (Student student : list) {
                        System.out.println(student);
                    }
                }
  • ArrayHandler : 將一條記錄封裝到一個Object陣列中
                    @Test
                public void demo5() throws SQLException{
                    QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
                    Object[] obj = qr.query("select * from user where id = ?", new ArrayHandler(),3);
                    for (Object object : obj) {
                        System.out.println(object);
                    }
                }
  • ArrayListHandler :.將多條記錄封裝到一個裝有Object陣列的List集合中去.
        ScalarHandler : 將單個值封裝.
                @Test
                public void demo3() throws SQLException{
                    QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
                    Object obj = qr.query("select count(*) from user", new ScalarHandler());
                    System.out.println(obj);
                }
  • ColumnListHandler() : 將一列(欄位)的值封裝到List集合中 ()可以傳入引數,傳入的是要封裝的列.
                @Test
                public void demo4() throws SQLException{
                    QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
                    List<Object> list = qr.query("select nickname from user ", new ColumnListHandler());
                    for (Object obj : list) {
                        System.out.println(obj);
                    }
                }
  • MapHandler: 將一條記錄封裝到一個Map集合中,Map集合的key是列名(欄位名) values是表中列的記錄值 //結果 {id=1, username=小張, nickname=張三, age=12, password=123}

  • MapListHandler : 將多條記錄封裝到一個裝有Map集合中的List集合中

                @Test
                public void demo6() throws SQLException{
                    QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
                    List<Map<String,Object>> list = qr.query("select * from user", new MapListHandler());
                    for (Map<String, Object> map : list) {
                        System.out.println(map);
                    }    
                }

第一次寫部落格,如果有錯誤的地方指正