JDBC實現數據庫的連接和操作:

  • 一、連接數據庫
  • 1.Java代碼
  • 2.配置文件`myjdbc.properties`
  • 二、創建執行語句,Statement語句
  • 三、執行SQL語句
  • 1.實現數據庫的操作:`增刪改`,此時並沒有返回值
  • 2.實現數據庫的操作:`查`
  • 3.用到的Employees類

一、連接數據庫


1.Java代碼

import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Java連接數據庫 JDBC:
 * 一、創建連接 Connection 對象
 * 二、創建執行的語句 Statement 對象
 * 三、執行 SQL 語句
 *
 * 一、創建連接
 * 1.最耿直,直接創建對象。由於獲取驅動的實例化對象時使用了第三方的包 mysql.jdbc.Driver()
 *   Driver driver = new com.mysql.jdbc.Driver();
 *
 * 2.法一不利於代碼的移植和擴展性,所以在此基礎之上,利用反射的方法創建 Driver 對象
     * 獲取類對象 getClassname()
     * 獲取構造器,創建對象 getDeclaredConstructor().newInstance()
     * 獲取指定的方法 getMethod(方法名,參數列表),如 getMethod("setPrice", int.class)
     * 使用類的方法進行初始化 invoke(創建的對象, 14)
 *
 *   Class clazz = Class.forName("com.mysql.jdbc.Driver");
 *   Driver driver = (Driver)clazz.getDeclaredConstructor().newInstance();
 *
 * 3.直接使用驅動不方便,引入驅動管理的實現類,進一步簡化。並且在 mysql的Driver實現類中已經
 *   聲明瞭註冊驅動
 *   Class.forName("com.mysql.jdbc.Driver");
 *   Connection conn = DriverManager.getConnection(url, user, password);
 *
 * 4.直接寫死了用户名、密碼等信息,不安全、不方便,引入配置文件
 *   連接mysql,jdbc:mysql:協議,localhost:ip地址,3306:默認mysql的端口號,test:連接的數據庫名稱
 *         String string = "jdbc:mysql://localhost:3306/test";
 *         Properties info = new Properties();
 *         // 將用户名和密碼封裝在Properties中
 *         info.setProperty("user", "tom");
 *         info.setProperty("password", "123");
 *    配置文件讓用户能夠脱離程序本身去修改相關的變量設置。
 *        1、從目標路徑 myjdbc.properites 中獲取輸入流對象
 *        2、使用 Properties類的 load()方法從字節輸入流中獲取數據
 *        3.使用 Properties類的 getProperty(String key)方法,根據參數key獲取value
 *
 *

 * @Auther:sommer1111
 * @date 2020/10/10 17:36
 */
public class _01_ConnectionMySQL {
    public static void main(String[] args) throws Exception{
        //1.從目標路徑myjdbc.properites中獲取輸入流對象
        InputStream in = _01_ConnectionMySQL.class.getClassLoader().getResourceAsStream("myjdbc.properties");

        //2.使用Properties類的load()方法從字節輸入流中獲取數據
        Properties pro = new Properties();
        pro.load(in);
        String driverClass = pro.getProperty("driverClass");
        String url = pro.getProperty("url");
        String name = pro.getProperty("user");
        String password = pro.getProperty("password");

        //3.加載驅動
        Class.forName(driverClass);

        //4.獲取連接
        Connection connect = DriverManager.getConnection(url,name,password);
        System.out.println(connect);
    }
}

2.配置文件myjdbc.properties

#設置配置信息
url=jdbc:mysql://localhost:3306/myemployees
user=tom
password=123
driverClass=com.mysql.jdbc.Driver


二、創建執行語句,Statement語句


將代碼專門抽象成一個工具類

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

/**
 * @Auther:sommer1111
 * @date 2020/10/13 16:25
 */
public class statementUtil {
    //獲取連接
    public static Connection getConnect() throws Exception {
        InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("myjdbc.properties");
        Properties ps = new Properties();
        ps.load(in);

        String driverClass = ps.getProperty("driverClass");
        String url = ps.getProperty("url");
        String user = ps.getProperty("user");
        String password = ps.getProperty("password");

        Class.forName(driverClass);
        return DriverManager.getConnection(url, user, password);
    }

    //關閉資源
    public static void closeConnetion(Connection con,PreparedStatement sta){
            try {
                if(con != null){
                    con.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }

            try {
                if(sta != null){
                    sta.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
    }

    //增加一個關閉資源
    public static void closeConnetion(Connection con, PreparedStatement sta, ResultSet rs){
        try {
            if(con != null){
                con.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        try {
            if(sta != null){
                sta.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

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


    //設置statment
    public static void update(String sql,Object ...args) {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            //1.預編譯
            connection = getConnect();
            statement = connection.prepareStatement(sql);
            //2.填充佔位符
            for(int i = 0;i<args.length;i++){
                statement.setObject(i+1,args[i]);
            }
            //3.執行
            statement.execute();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            closeConnetion(connection,statement);
        }
    }
}

三、執行SQL語句


1.實現數據庫的操作:增刪改,此時並沒有返回值

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 實現創建數據庫語句的操作(增刪改,沒有返回)
 *
 * 1.獲取數據庫連接
 *             InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("myjdbc.properties");
 *             Properties ps = new Properties();
 *             ps.load(in);
 *             String driverClass = ps.getProperty("driverClass");
 *             String url = ps.getProperty("url");
 *             String user = ps.getProperty("user");
 *             String password = ps.getProperty("password");
 *             Class.forName(driverClass);
 *             connection = DriverManager.getConnection(url, user, password);
 *
 * 2.預編譯sql語句,返回PreparedStatement的實例
 *             String sql = new String("UPDATE locations SET street_address = ? WHERE location_id = ?;");
 *             statement = connection.prepareStatement(sql);
 *
 * 3.填充佔位符
 *             statement.setObject(1,"wuhan");
 *             statement.setObject(2,"2200");
 * 4.執行
 *             statement.execute();
 * 5.資源的關閉(都需要用 try catch)
 *             statement.close();
 *             connection.close()
 *
 * 優化:
 * 1.將數據庫的連接、預編譯、關閉資源都封裝成方法 statementUtil,簡化代碼
 *
 * @Auther:sommer1111
 * @date 2020/10/13 15:38
 */
public class _02_Statement {
    public static void main(String[] args) {

        String sql = "UPDATE locations SET street_address = ? WHERE location_id = ?;";
        Object[] arg = {"jiangxi","2300"};
        statementUtil.update(sql,arg);

//        Connection connection = null;
//        PreparedStatement statement = null;
//        try {
//            //1.獲取數據庫連接
//            InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("myjdbc.properties");
//            Properties ps = new Properties();
//            ps.load(in);
//            String driverClass = ps.getProperty("driverClass");
//            String url = ps.getProperty("url");
//            String user = ps.getProperty("user");
//            String password = ps.getProperty("password");
//            Class.forName(driverClass);
//            connection = DriverManager.getConnection(url, user, password);
//
//
//            //2.預編譯sql語句,返回PreparedStatement的實例
//            String sql = new String("UPDATE locations SET street_address = ? WHERE location_id = ?;");
//            statement = connection.prepareStatement(sql);
//            //3.填充佔位符
//            statement.setObject(1,"wuhan");
//            statement.setObject(2,"2200");
//
//            //4.執行
//            statement.execute();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }finally {
//            //5.資源的關閉
//            if(statement != null){
//                try {
//                    statement.close();
//                } catch (SQLException throwables) {
//                    throwables.printStackTrace();
//                }
//            }
//            if(connection != null){
//                try {
//                    connection.close();
//                } catch (SQLException throwables) {
//                    throwables.printStackTrace();
//                }
//            }
//        }
    }
}

2.實現數據庫的操作:

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;

/**
 * JDBC 實現數據庫的查詢
 * 一、分析:
 * 1. 使用 PreparedStatement實現查詢操作,查詢操作的區別在於會有一個數據返回
 * 2. 返回的數據用一個類封裝 ResultSet,這個表中只有數據,但是如果我們還需要獲取表頭信息
 * 3. 用 getMetaData 獲取關於 ResultSet 對象中列的類型和屬性信息的對象 ResultSetMetaData
 * 4. ResultSet 資源也需要釋放
 *
 * 二、實現:
 * 1.獲取連接
 * 2.執行sql語句,得打結果返回 ResultSet,ResultSet rs = ps.executeQuery();
 * 3.要想顯示結果,將數據讀取出來封裝在一個 Collection 對象中 key-value 鍵值對
 *   |--讀取出表頭信息:
 *      (1)獲取元數據集,ResultSetMetaData rsmd = rs.getMetaData();
 *      (2)獲取結果集中的列數,迭代讀取元數據集的表頭:
 *          int columnCount = rsmd.getColumnCount();
 *          String columnName = rsmd.getColumnName(i + 1);
 *      (3)獲取列值,此時列值屬性失去,都變成了 Object
 * 			Object columValue = rs.getObject(i + 1);
 * 		(4)利用反射恢復列值在 Collection 對象的屬性,並添加到集合中:
 * 	        Field field = Customer.class.getDeclaredField(columnLabel);
 * 			field.setAccessible(true);使在用反射時能訪問私有變量
 * 			field.set(cust, columValue);
 * 4.關閉資源
 *
 * 三、筆記
 *  1.查詢需要調用PreparedStatement 的 executeQuery() 方法,查詢結果是一個ResultSet 對象
 *    ResultSet通過指針迭代取數據,常用方法有:
 *      next(),用於迭代的指針,指向下一個值。
 *      getObject(),獲取列值。
 *
 *  2.ResultSetMetaData對象的常用方法
 *    getColumnName(int column):獲取指定列的名稱
 *    getColumnLabel(int column):獲取指定列的別名(MySQL中的別名,推薦使用)
 *    getColumnCount():返回當前 ResultSet 對象中的列數。
 *    getColumnTypeName(int column):檢索指定列的數據庫特定的類型名稱。
 *
 * @Auther:sommer1111
 * @date 2020/10/14 15:35
 */


public class _03_StatementQuery {
    public static void main(String[] args) {
        String sql = "SELECT employee_id,last_name,email,salary FROM employees WHERE employee_id>?;";
        Collection<Employees> employees = queryForEmployees(sql, 128);
        for(Employees employee:employees){
            System.out.println(employee);
        }

    }

    //基本實現
    public static Collection<Employees> queryForEmployees(String sql, Object...args) {
        statementUtil util = null;
        Connection connect = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Collection<Employees> list = new ArrayList<>();

        try {
            util = new statementUtil();
            connect = util.getConnect();
            ps = connect.prepareStatement(sql);

            for (int i = 0; i < args.length; i++) {
                ps.setObject(i+1,args[i]);
            }

            //得到數據集
            rs = ps.executeQuery();
            //獲取元數據
            ResultSetMetaData rsmd = rs.getMetaData();
            //開始讀取值

            while(rs.next()){//一行的數據為一個next
                Employees em = new Employees();
                int columnCount = rsmd.getColumnCount();
                for (int i = 0; i < columnCount; i++) {
                    //獲取數據
                    Object value = rs.getObject(i+1);
                    //獲取列名,最好使用別名來獲取
                    String columnName = rsmd.getColumnLabel(i + 1);
                    //恢復屬性
                    Field field = Employees.class.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(em,value);
                }
                list.add(em);
            }
            return list;

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            util.closeConnetion(connect,ps,rs);
        }
        return null;
    }

    //優化增強擴展性,將具體的類換成泛型
    public static <T>T queryForEmployees(Class<T> clazz,String sql, Object...args) throws Exception {
        //修改創建類的語句
        T t = clazz.getDeclaredConstructor().newInstance();
        //修改反射設值的語句,其餘不變
        //field.set(t,value);
        return null;
    }
}

3.用到的Employees類

/**
 * @Auther:sommer1111
 * @date 2020/10/14 16:28
 */
class Employees {
    private int employee_id;
    private String last_name;
    private String email;
    private double salary;

    public Employees() {
    }

    public Employees(int employee_id, String last_name, String email, int salary) {
        this.employee_id = employee_id;
        this.last_name = last_name;
        this.email = email;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employees{" +
                "employee_id=" + employee_id +
                ", last_name='" + last_name + '\'' +
                ", email='" + email + '\'' +
                ", salary=" + salary +
                '}';
    }

    public int getEmployee_id() {
        return employee_id;
    }

    public void setEmployee_id(int employee_id) {
        this.employee_id = employee_id;
    }

    public String getLast_name() {
        return last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public double getSalary() {
        return salary;
    }

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