1. 程式人生 > 資料庫 >MySQL - JDBC&資料庫連線池

MySQL - JDBC&資料庫連線池

MySQL - JDBC&資料庫連線池

目錄

1 JDBC

1.1 概念

  • Java Data Base Connectivity
  • 執行SQL的Java API
  • Java訪問多種資料庫的統一規範(介面)
  • 資料庫廠商實現介面並提供驅動jar包
1.1.1 JDBC專案準備
  • 新建專案並匯入JDBC相關jar包
1.1.2 JDBC連線步驟
1.1.2.1 註冊驅動
Class.forName("com.mysql.jdbc.Driver");

原理:

  • JDBC3開始可不用註冊驅動直接使用,該步驟可以省略
1.1.2.2 獲取連線
  • connection介面表示連線物件,具體實現類由資料庫廠商實現
  • Driver Manager的getConnection方法可以獲得連線物件
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8","root","123456");

該Connection物件有com.mysql.jdbc提供

1.1.2.3 獲取語句執行物件
  • statement類,語句物件,傳送SQL語句給伺服器,執行靜態SQL並返回結果
  • 通過Connection連線物件的createStatement方法獲取
  • statement常用方法:
    • int executeUpdate(String sql); DML,DDL語句; 返回值代表受影響的行數
    • ResultSet executeQuery(String sql); DQL語句; 返回ResultSet結果集物件
1.1.2.4 處理結果集物件(DQL)
  • DQL語句得到的是ResultSet結果集物件
  • ResultSet介面封裝了查詢的結果
  • 介面方法:
    • boolean next(); 如果下一行還有記錄返回true,沒有記錄返回false
    • xxx getXxx (String or int); 過載方法; 通過列名返回,引數String,返回不同的型別; 通過列號返回,引數是int,從1開始,返回不同型別
Statement statement = connection.createStatement();

        String sql = "SELECT * FROM jdbc_user";

        ResultSet resultSet = statement.executeQuery(sql);


        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString(2);
            String password = resultSet.getString("PASSWORD");
            Date birthday = resultSet.getDate(4);
            System.out.println(id+" "+username+" "+password+" "+birthday);
        }

1.1.2.5 釋放資源
  • 先開起後關閉
  • resultset(僅DQL查詢時使用) -> statement - > connection
		resultSet.close();   
        connection.close();
        statement.close();

1.2 JDBC工具類(Utils)

1.2.1 編寫JDBCUtils工具類
  • 將連線資訊定義成字串常量
  • 編寫靜態程式碼塊註冊驅動
  • 編寫靜態方法獲取連線物件
  • 編寫關閉資源的方法(過載對於DQL和非DQL)
1.2.1.1 將連線資訊定義成字串常量
public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/bd4?characterEncoding=UTF-8";
    public static final String USERNAME = "root";
    public static final String PASSWORD = "123456";
1.2.1.2 編寫靜態程式碼塊註冊驅動
static {
        try {
            Class.forName(DRIVERNAME);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
1.2.1.3 編寫靜態方法獲取連線物件
public static Connection getConnection(){
        try {
            Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
1.2.1.4 編寫關閉資源的方法(過載對於DQL和非DQL)
public static void Close(Connection con, Statement statement){
        if (con!=null && statement!= null){
            try {
                statement.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void Close(Connection con, Statement statement, ResultSet resultSet){
        if (con!= null && statement!=null && resultSet!=null){
            try {
                resultSet.close();
                statement.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

1.3 SQL注入問題

  • 使用OR,前面使用者名稱密碼錯誤也可以拿到資料因為or1真為真
select * from jdbc_user where username = 'tom' and PASSWORD = '123' or '1' = '1';

程式碼演示:SQL語句為

String sql = "select * from jdbc_user where username = '" + username + "' and PASSWORD = '" + password + "'";

當用戶輸入password為:

abc' or '1' = '1

就會產生SQL注入

1.3.1 如何解決SQL注入?
  • 不能讓使用者輸入的密碼和SQL語句進行簡單的字串拼接
  • 輸入時使用Scanner.next而不是nextLine接收,這樣無法拼接空格
  • 拿到資料後判斷SQL返回結果的使用者名稱是否與使用者輸入的使用者名稱相同
1.3.1.1 預處理物件防止SQL注入
  • PreparedStatement是Statement介面的子介面,繼承父介面所有方法

  • 預編譯的SQL語句:

    • 執行效率更高
    • 更安全,可防止SQL注入
  • ? 佔位符來設定引數

具體流程:

  • 編寫SQL,對於引數使用?佔位符
  • 通過Connection物件的preparestatement(sql) 有參方法拿到預處理物件
  • 呼叫預處理物件的setXXX(int 佔位符位置,XXX 要設定的值)給引數賦值
  • 呼叫預處理物件的execute方法執行SQL查詢

示例:

Connection connection = JDBCUtils.getConnection();

        String sql = "select * from jdbc_user where username = ? and PASSWORD = ?";

        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setString(1,"tom");
        preparedStatement.setString(2,"123456");

        ResultSet resultSet = preparedStatement.executeQuery();

        while (resultSet.next()){
            System.out.println(resultSet.getString("username")+" "+resultSet.getString("PASSWORD"));
        }

        JDBCUtils.Close(connection,preparedStatement,resultSet);
    }
1.3.1.2 statement和preparedstatement

當執行SQL時,比如插入資料(insert into jdbc_user values .... )

  • statement物件每執行一條SQL語句就會先發給資料庫先編譯再執行

    • 插入多少條資料資料庫就需要編譯多少次
    • 執行靜態SQL
  • preparedstatement物件執行SQL語句資料庫只需要預編譯一次

    • 然後將預編譯的SQL儲存起來(快取)
    • 插入多條資料時只需設定引數即可
    • 可包含動態引數"?"

1.4 事務API

Connection方法實現事務

方法 說明
void setAutoCommit(boolean autocommit) 是否自動提交,true自動提交
void commit() 提交事務
viod rollback() 回滾事務

示例:模擬轉賬操作

  • 獲取connection連線物件
  • 開啟事務(關閉事務自動提交)
  • 獲取preparedstatement物件
  • 設定引數,正常則手動提交
  • 出現異常則回滾事務
  • 關閉資源
Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = JDBCUtils.getConnection();

            connection.setAutoCommit(false);
            String sql = "update account set money = ? where NAME = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setDouble(1,500.0);
            preparedStatement.setString(2,"tom");
            preparedStatement.executeUpdate();
            
            preparedStatement.setDouble(1,1500.0);
            preparedStatement.setString(2,"jack");

            preparedStatement.executeUpdate();

            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
            JDBCUtils.Close(connection,preparedStatement);
        }
    }

2 資料庫連線池

2.1 連線池介紹

  • 管理資料庫連線,可重複使用連結
  • 關閉連線不代表銷燬connection,只是進行了歸還

如何使用連線池:

  • Java官方為連線池提供了公共的介面java.sql.DataSource
  • 廠商實現該介面使用者即可方便使用者切換不同連線池
  • 常用連線池:
    • DBCP
    • C3P0
    • Druid

2.2 常用連線池

2.2.1 DBCP連線池
2.2.1.1 概念:
  • 開源
  • 屬於Apache
  • tomcat內建連線池

使用方法:

  • 匯入相關Jar包
2.2.1.2 DBCP工具類
  • 定義常量儲存資料庫連線相關資訊(Drivername,url,username,password)
  • 建立連線池物件BasicDataSource,由DBCP提供的實現類
  • 編寫靜態程式碼塊對連線池物件進行配置
  • 編寫方法從連線池物件種獲取連線
  • 釋放資源

程式碼:

import org.apache.commons.dbcp.BasicDataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DBCPUtils {
    public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8";
    public static final String USERNAME = "root";
    public static final String PASSWORD = "123456";

    public static BasicDataSource dataSource = new BasicDataSource();

    static {
        dataSource.setDriverClassName(DRIVERNAME);
        dataSource.setUrl(URL);
        dataSource.setUsername(USERNAME);
        dataSource.setPassword(PASSWORD);
    }

    public static Connection getConnection(){
        try {
            Connection connection = dataSource.getConnection();
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void close(Connection con, Statement statement){
        if (con!=null && statement != null){
            try {
                statement.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(Connection con, Statement statement, ResultSet resultSet){
        if (con!=null && statement != null && resultSet!= null){
            try {
                resultSet.close();
                statement.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

測試類:

Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = DBCPUtils.getConnection();

            String sql = "select * from jdbc_user where username = ?";

            preparedStatement = connection.prepareStatement(sql);

            preparedStatement.setString(1,"tom");

            resultSet = preparedStatement.executeQuery();

            while (resultSet.next()) {
                System.out.println(resultSet.getString("username")+" "+resultSet.getString(3));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBCPUtils.close(connection,preparedStatement,resultSet);
        }

常見配置項:

屬性 描述
driverClassName 資料庫驅動名稱(mysql時 - com.mysql.jdbc.Driver)
url 資料庫地址
username 使用者名稱
password 密碼
maxActive 最大連線數量(預設8)
maxIdle 最大空閒連線(預設8)
minIdle 最小空閒連線(預設0)
intialSize 初始化連線(預設0)
2.2.2 C3P0連線池
2.2.2.1 概念
  • 開源
  • Hibernate,Spring框架使用

使用方式:

可配置xml檔案儲存c3p0相關配置

c3p0-config.xml

<c3p0-config>

    <!--預設配置-->
    <default-config>

        <!-- initialPoolSize:初始化時獲取三個連線,
              取值應在minPoolSize與maxPoolSize之間。 -->
        <property name="initialPoolSize">3</property>

        <!-- maxIdleTime:最大空閒時間,60秒內未使用則連線被丟棄。若為0則永不丟棄。-->
        <property name="maxIdleTime">60</property>

        <!-- maxPoolSize:連線池中保留的最大連線數 -->
        <property name="maxPoolSize">100</property>
        <!-- minPoolSize: 連線池中保留的最小連線數 -->
        <property name="minPoolSize">10</property>

    </default-config>

    <!--配置連線池mysql-->

    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db5?characterEncoding=UTF-8</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
    </named-config>
    <!--配置連線池2,可以配置多個-->

</c3p0-config>
2.2.2.2 c3p0工具類
  • 不需要定義常量儲存資料庫連線相關資訊(因為配置xml檔案)
  • 建立連線池物件ComboPooledDataSource,由c3p0提供的實現類
    • new ComboPooledDataSource() 無參構造使用的是xml中的預設配置
    • new ComboPooledDataSource(configName) 有參構造使用的是xml中的指定配置
  • 編寫方法從連線池物件中拿到connection連線物件
  • 釋放資源
import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class C3P0Utils {
    public static ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");

    public static Connection getConnection(){
        try {
            Connection connection = dataSource.getConnection();
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void close(Connection con, Statement statement){
        try {
            if (con!= null && statement!= null){
                statement.close();
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(Connection con, Statement statement, ResultSet resultSet){
        try {
            if (con!= null && statement!= null && resultSet!=null){
                resultSet.close();
                statement.close();
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

C3P0測試類:

Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            connection = C3P0Utils.getConnection();
            statement = connection.createStatement();

            String sql = "select * from jdbc_user";

            resultSet = statement.executeQuery(sql);

            while (resultSet.next()){
                System.out.println(resultSet.getInt(1)+" "+resultSet.getString(2)+" "+ resultSet.getDate(4));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            C3P0Utils.close(connection,statement,resultSet);
        }
2.2.3 Druid連線池
2.2.3.1 概念

使用方式:

配置檔案:

  • properties檔案形式
  • 名稱任意,檔案路徑任意,建議放到統一的resource資源目錄下

druid.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db5?characterEncoding=UTF-8
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
2.2.3.2 Druid工具類
  • 不需要定義常量來儲存資料庫連線相關資訊(properties檔案)
  • 獲取資料庫連線池物件,通過工廠來獲取DruidDataSourceFactory的createDataSource方法
  • createDataSource(Properties p)引數傳入properties屬性集物件
  • properties屬性集物件通過load方法傳入從位元組流獲取的對應properties檔案 - getResourceAsStream()方法
  • 通過從工廠中拿到的連線池物件建立connection物件
  • 釋放資源
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DruidUtils {
    public static DataSource dataSource;

    static {
        try {
            Properties p = new Properties();

            InputStream resourceAsStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");

            p.load(resourceAsStream);

            dataSource = DruidDataSourceFactory.createDataSource(p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        try {
            Connection connection = dataSource.getConnection();
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void close (Connection connection, Statement statement){
        if (connection != null && statement != null){
            try {
                statement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close (Connection connection, Statement statement, ResultSet resultSet){
        if (connection != null && statement != null && resultSet!= null){
            try {
                resultSet.close();
                statement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

示例:查詢工資3000到5000的員工姓名

Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            connection = DruidUtils.getConnection();

            statement = connection.createStatement();

            String sql = "select ename from employee where salary between 3000 and 5000";

            resultSet = statement.executeQuery(sql);

            while (resultSet.next()){
                System.out.println(resultSet.getString("ename"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DruidUtils.close(connection,statement,resultSet);
        }
2.2.4 DBUtils工具類
2.2.4.1 基礎概念
  • 解決JDBC程式碼冗餘問題
  • APache對JDBC進行簡單封裝的開源工具

使用方式:

核心功能:

  • QueryRunner

    • SQL語句操作的API
  • ResulSetHandler介面

    • DQL後自定義封裝結果集
  • DbUtils類

    • 封裝了關閉資源和事務處理的方法
2.2.4.2 表和類的關係

JavaBean類對應一張表

  • 實現序列化介面 Serializable
  • 提供私有欄位 private 型別 變數名 - 對應表中欄位
  • get和set方法
  • 無參構造
2.2.4.3 QueryRunner 核心類
  • 構造方法
    • 手動模式:QueryRunner()
    • 自動模式(傳入資料庫連線池物件):QueryRunner(DataSource ds) 提供資料來源(連線池),DbUtils自動維護連線
//自定義Druid工具類中需要加入獲取連線池物件的方法
public static DataSource getDataSource(){
        return dataSource;
    }
    
//手動
QueryRunner queryRunner = new QueryRunner();

//自動
QueryRunner queryRunner1 = new QueryRunner(DruidUtils.getDataSource());
  • 常用方法
    • update(Connection con, String sql, Object ... params) 表資料的增刪改操作
    • query(Connection con, String sql, ResultSetHandler resultset, Object ... params) 表資料的查詢操作

update:

  • 建立QueryRunner例項物件(手動模式呼叫update方法時需要傳入connection物件,自動模式呼叫update方法時不需要傳入connection物件)
  • 編寫SQL語句,使用? 佔位符
  • 設定佔位符引數
  • 呼叫update方法
  • 釋放資源

示例:插入一條資料

try {
            QueryRunner queryRunner = new QueryRunner();

            String sql = "insert into employee values(?,?,?,?,?,?)";

            Object[] params = {null,"劉翔",35,"男",9000,"1997-09-18"};

            Connection connection = DruidUtils.getConnection();

            queryRunner.update(connection,sql,params);

            DbUtils.closeQuietly(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        }

示例:修改一條資料

try {
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());

            String sql = "update employee set salary = ? where ename = ?";

            Object[] params = {5000, "劉翔"};

            queryRunner.update(sql,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }

示例:刪除一條資料

try {
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());

            String sql = "delete from employee where eid = ?";


            queryRunner.update(sql,11);
        } catch (SQLException e) {
            e.printStackTrace();
        }
2.2.4.4 ResulSetHandler (介面)
  • 對查詢出來的ResultSet結果集進行處理

常用實現類:

ResultSetHandler 實現類 描述
ArrayHandler 將結果集中的第一條記錄封裝到一個Object[]陣列中,陣列中的每一個元素就是這 條記錄中的每一個欄位的值
ArrayListHandler 將結果集中的每一條記錄都封裝到一個Object[]陣列中,將這些陣列在封裝到List集 閤中
BeanHandler 將結果集中第一條記錄封裝到一個指定的javaBean中.
BeanListHandler 將結果集中每一條記錄封裝到指定的javaBean中,再將這些javaBean在封裝到List 集合中
ColumnListHandle 將結果集中指定的列的欄位值,封裝到一個List集合中
KeyedHandler 將結果集中每一條記錄封裝到Map<String, Oject>,在將這個map集合做為另一個 Map的value,另一個Map集合的key是指定的欄位的值
MapHandler 將結果集中第一條記錄封裝到了Map<String, Oject>集合中,key就是欄位名稱, value就是欄位值
MapListHandler 將結果集中每一條記錄封裝到了Map<String, Oject>集合中,key就是欄位名稱, value就是欄位值,在將這些Map封裝到List集合中
ScalarHandler 它是用於封裝單個數據。例如 select count(*) from 表操作

3個不同map的區別

  • MapListHandler (查詢結果為多條記錄):每一個Map對應表中的一條資料,Map裡的key為欄位名,value為值,然後用一個List將所有Map封裝起來對應表。 遍歷資料需要先遍歷List的每一個Map拿到每一條資料,再通過EntrySet拿到每一個Map的所有key:value對
try {
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());

            String sql= "select * from employee";

            List<Map<String, Object>> query = queryRunner.query(sql, new MapListHandler());

            for (Map<String, Object> map : query) {
                Set<Map.Entry<String, Object>> entries = map.entrySet();
                for (Map.Entry<String, Object> entry : entries) {
                    System.out.print(entry.getKey()+":"+entry.getValue()+" ");
                }
                System.out.println();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
      
結果:
eid:1 ename:李清照 age:22 sex:女 salary:4000.0 empdate:2018-11-12 
eid:2 ename:林黛玉 age:20 sex:女 salary:5000.0 empdate:2019-03-14 
eid:3 ename:杜甫 age:40 sex:男 salary:6000.0 empdate:2020-01-01 
eid:4 ename:李白 age:25 sex:男 salary:3000.0 empdate:2017-10-01 
eid:9 ename:zzc age:18 sex:男 salary:3500.0 empdate:2019-09-16 
eid:10 ename:abc age:18 sex:男 salary:3600.0 empdate:2019-09-16
  • MapHandler(查詢結果為1條記錄):Map對應一條查詢到的語句,Map裡的key為欄位名,value為值,遍歷結果遍歷entrySet
try {
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());

            String sql= "select * from employee where ename = ?";

            Map<String, Object> result = queryRunner.query(sql, new MapHandler(), "李白");

            for (Map.Entry<String, Object> entry : result.entrySet()) {
                System.out.print(entry.getKey()+":"+entry.getValue()+" ");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
  • KeyedHandler:每一條記錄對應一個Map,不同之處在於對於表該實現類用Map和每一條記錄的指定欄位值來對應
try {
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());

            String sql= "select ename,age from employee";

            Map<Object, Map<String, Object>> query = queryRunner.query(sql, new KeyedHandler<>());

            for (Map.Entry<Object, Map<String, Object>> entry : query.entrySet()) {
                System.out.print(entry.getKey()+": ");
                Set<Map.Entry<String, Object>> entries = entry.getValue().entrySet();
                for (Map.Entry<String, Object> objectEntry : entries) {
                    System.out.print(objectEntry.getKey()+":"+objectEntry.getValue()+" ");
                }

                System.out.println();
            }


        } catch (SQLException e) {
            e.printStackTrace();
        }

使用Bean物件:

  • 根據表的對應欄位建立Bean物件
import java.io.Serializable;
import java.util.Date;

public class Employee implements Serializable {
    /*
        eidint(11) NOT NULL
        enamevarchar(20) NULL
        ageint(11) NULL
        sexvarchar(6) NULL
        salarydouble NULL
        empdatedate NULL
     */
    private static final long serialVersionUID = 2927021897478991450L;

    private int eid;
    private String ename;
    private int age;
    private String sex;
    private double salary;
    private Date empdate;

    public Employee() {
    }

    public int getEid() {
        return eid;
    }

    public void setEid(int eid) {
        this.eid = eid;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Date getEmpdate() {
        return empdate;
    }

    public void setEmpdate(Date empdate) {
        this.empdate = empdate;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "eid=" + eid +
                ", ename='" + ename + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", salary=" + salary +
                ", empdate=" + empdate +
                '}';
    }
}

示例:

 try {
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());

            String sql= "select * from employee";

            List<Employee> query = queryRunner.query(sql, new BeanListHandler<Employee>(Employee.class));

            for (Employee employee : query) {
                System.out.println(employee.toString());
            }


        } catch (SQLException e) {
            e.printStackTrace();
        }
2.2.4.5 批處理
  • 一次操作執行多條SQL語句

批處理的實現:

  • Statement和PreparedStatement物件都支援批處理
  • PreparedStatement:
    • void addBatch() - 將指定SQL新增到次Statement物件中
    • int[] executeBatch() - 提交一批命令到資料庫中,返回陣列為受影響行數

mysql 批處理預設關閉,需要引數拼接在url後開啟

rewriteBatchedStatements=true
例如: url=jdbc:mysql://127.0.0.1:3306/db5?characterEncoding=UTF-8&rewriteBatchedStatements=true

3 MySQL元資料

  • 除了表之外的資料都是元資料
    • 查詢結果資訊: UPDATE 或 DELETE語句 受影響的記錄數
    • 資料庫和資料表的資訊: 包含了資料庫及資料表的結構資訊
    • MySQL伺服器資訊: 包含了資料庫伺服器的當前狀態,版本號等

Mysql獲取元資料常用命令:

-- 元資料相關的命令介紹
-- 1.檢視伺服器當前狀態
show status;
-- 2.檢視MySQl的版本資訊
select version();
-- 3.查詢表中的詳細資訊
show columns from table_name;
-- 4.顯示資料表的詳細索引資訊
show index from table_name; 
-- 5.列出所有資料庫
show databases:
-- 6.顯示當前資料庫的所有表
show tables :
-- 7.獲取當前的資料庫名
select database():

JDBC獲取元資料

元資料類:

  • DatabaseMetaData - 描述資料庫的元資料物件
  • ResultSetMetaData - 描述結果集的元資料物件

獲取元資料物件:呼叫 getMetaData ()方法

  • connection 連線物件, 呼叫 getMetaData () 方法,獲取的是DatabaseMetaData 資料庫元資料物件
  • PrepareStatement 預處理物件呼叫 getMetaData () , 獲取的是ResultSetMetaData , 結果集元資料物件

DatabaseMetaData 常用方法:

  • getURL() : 獲取資料庫的URL
  • getUserName(): 獲取當前資料庫的使用者名稱
  • getDatabaseProductName(): 獲取資料庫的產品名稱
  • getDatabaseProductVersion(): 獲取資料的版本號
  • getDriverName(): 返回驅動程式的名稱
  • isReadOnly(): 判斷資料庫是否只允許只讀 true 代表只讀

ResultSetMetaData的常用方法:

  • getColumnCount() : 當前結果集共有多少列
  • getColumnName(int i) : 獲取指定列號的列名, 引數是整數 從1開始
  • getColumnTypeName(int i): 獲取指定列號列的型別, 引數是整數 從1開始