java基礎(29):JDBC、DBUtils

1. JDBC

1.1 JDBC概述

JDBCJava Data Base Connectivity,java數據庫鏈接)是一種用於執行SQL語句的Java API,能夠爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。是Java訪問數據庫的標準規範java

JDBC提供了一種基準,據此能夠構建更高級的工具和接口,使數據庫開發人員可以編寫數據庫應用程序。mysql

JDBC須要鏈接驅動,驅動是兩個設備要進行通訊,知足必定通訊數據格式,數據格式由設備提供商規定,設備提供商爲設備提供驅動軟件,經過軟件能夠與該設備進行通訊。sql

今天咱們使用的是mysql的驅動mysql-connector-java-5.1.39-bin.jar數據庫

1.2 JDBC原理

Java提供訪問數據庫規範稱爲JDBC,而生產廠商提供規範的實現類稱爲驅動。服務器

JDBC是接口,驅動是接口的實現,沒有驅動將沒法完成數據庫鏈接,從而不能操做數據庫!每一個數據庫廠商都須要提供本身的驅動,用來鏈接本身公司的數據庫,也就是說驅動通常都由數據庫生成廠商提供。工具

1.3 案例分析

昨天咱們學習了sql語句的使用,並建立的分類表sort,今天咱們將使用JDBC對分類表進行增刪改查操做。學習

#建立數據庫 create database day22_JDBC; #使用數據庫 use day22_JDBC; ###建立分類表 create table sort( sid int PRIMARY KEY , sname varchar(100) ); #初始化數據 insert into sort(sname) values('家電'); insert into sort(sname) values('服飾'); insert into sort(sname) values('化妝品');

1.4 JDBC開發步驟

  1. 註冊驅動.
  2. 得到鏈接.
  3. 得到語句執行平臺
  4. 執行sql語句
  5. 處理結果
  6. 釋放資源.

1.4.1 導入驅動jar

建立lib目錄,用於存放當前項目須要的全部jar測試

選擇jar包,右鍵執行build path / Add to Build Pathui

1.4.2 API詳解:註冊驅動

代碼:Class.forName("com.mysql.jdbc.Driver");

JDBC規範定義驅動接口:java.sql.DriverMySql驅動包提供了實現類:com.mysql.jdbc.Driver編碼

DriverManager工具類,提供註冊驅動的方法 registerDriver(),方法的參數是java.sql.Driver,因此咱們能夠經過以下語句進行註冊:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

以上代碼不推薦使用,存在兩方面不足

  1. 硬編碼,後期不易於程序擴展和維護
  2. 驅動被註冊兩次。

一般開發咱們使用Class.forName() 加載一個使用字符串描述的驅動類。

若是使用Class.forName()將類加載到內存,該類的靜態代碼將自動執行。

經過查詢com.mysql.jdbc.Driver源碼,咱們發現Driver類「主動」將本身進行註冊

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

1.4.3 API詳解:得到連接

代碼:Connection con = DriverManager.getConnection (「jdbc:mysql://localhost:3306/mydb」,」root」,」root」);

獲取鏈接須要方法 DriverManager.getConnection(url,username,password),三個參數分別表示,url 須要鏈接數據庫的位置(網址) user用戶名  password 密碼

url比較複雜,下面是mysqlurl

jdbc:mysql://localhost:3306/mydb
JDBC規定url的格式由三部分組成,每一個部分中間使用冒號分隔。   第一部分是jdbc,這是固定的;   第二部分是數據庫名稱,那麼鏈接mysql數據庫,第二部分固然是mysql了;   第三部分是由數據庫廠商規定的,咱們須要瞭解每一個數據庫廠商的要求,mysql的第三部分分別由數據庫服務器的IP地址(localhost)、端口號(3306),以及DATABASE名稱(mydb)組成。

1.4.4 API詳解:得到語句執行平臺

String sql = "某SQL語句"; 獲取Statement語句執行平臺:Statement stmt = con.createStatement();

經常使用方法:

int executeUpdate(String sql); --執行insert update delete語句.

ResultSet executeQuery(String sql); --執行select語句.

boolean execute(String sql); --執行select返回true 執行其餘的語句返回false.

1.4.5 API詳解:處理結果集(執行insertupdatedelete無需處理)

ResultSet實際上就是一張二維的表格,咱們能夠調用其boolean next()方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,這時就可使用ResultSet提供的getXXX(int col)方法(與索引從0開始不一樣個,列從1開始)來獲取指定列的數據:

rs.next();//指向第一行
rs.getInt(1);//獲取第一行第一列的數據

經常使用方法:

Object getObject(int index) / Object getObject(String name) 得到任意對象

String getString(int index) / Object getObject(String name) 得到字符串

int getInt(int index) / Object getObject(String name) 得到整形

double getDouble(int index) / Object getObject(String name) 得到雙精度浮點型

1.4.6 API詳解:釋放資源

IO流同樣,使用後的東西都須要關閉!關閉的順序是先獲得的後關閉,後獲得的先關閉。

rs.close(); stmt.close(); con.close();

1.5 SQL注入問題

假設有登陸案例SQL語句以下:

SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸的密碼;

此時,當用戶輸入正確的帳號與密碼後,查詢到了信息則讓用戶登陸。可是當用戶輸入的帳號爲XXX 密碼爲:XXX’  OR ‘a’=’a時,則真正執行的代碼變爲:

SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;

此時,上述查詢語句時永遠能夠查詢出結果的。那麼用戶就直接登陸成功了,顯然咱們不但願看到這樣的結果,這即是SQL注入問題。

爲此,咱們使用PreparedStatement來解決對應的問題。

1.6 API詳解:預處理對象

使用PreparedStatement處理對象時,建議每條sql語句全部的實際參數,都使用逗號分隔。

 

String sql = "insert into sort(sid,sname) values(?,?)";; PreparedStatement預處理對象代碼: PreparedStatement psmt = conn.prepareStatement(sql)

 

經常使用方法:

1.執行SQL語句:

 

 

int executeUpdate(); --執行insert update delete語句.

 

ResultSet executeQuery(); --執行select語句.

 

boolea execute(); --執行select返回true 執行其餘的語句返回false.

 

 

2.設置實際參數

 

 

void setXxx(int index, Xxx xx) 將指定參數設置爲給定Java的xx值。在將此值發送到數據庫時,驅動程序將它轉換成一個 SQL Xxx類型值。

 

例如:

 

 

setString(2, "家用電器") 把SQL語句中第2個位置的佔位符? 替換成實際參數 "家用電器"

 

1.7 處理對象executeUpdate方法

 

 

經過預處理對象的executeUpdate方法,完成記錄的insert\update\delete語句的執行。操做格式統一以下:

 

1. 註冊驅動

 

2. 獲取鏈接

 

3. 獲取預處理對象

 

4. SQL語句佔位符設置實際參數

 

5. 執行SQL語句

 

6. 釋放資源

 

 

1.7.1 插入記錄:insert

 

 

實現向分類表中插入指定的新分類

 

 

public void demo01() throws Exception { // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root"); // 3得到預處理對象
        String sql = "insert into sort(sname) values(?)"; PreparedStatement stat = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數
        stat.setString(1, "奢侈品"); // 5執行SQL語句
        int line = stat.executeUpdate(); System.out.println("新添加記錄數:" + line); // 6釋放資源
 stat.close(); conn.close(); }

 

1.7.2 更新記錄:update

 

 

實現更新分類表中指定分類ID所對應記錄的分類名稱

 

 

public void demo02() throws Exception { // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root"); // 3得到預處理對象中
        String sql = "update sort set sname=? where sid=?"; PreparedStatement stat = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數
        stat.setString(1, "數碼產品"); stat.setInt(2, 1);      // 5執行SQL語句
        int line = stat.executeUpdate(); System.out.println("更新記錄數:" + line); // 6釋放資源
 stat.close(); conn.close(); }

 

1.7.3 刪除記錄:delete

 

 

實現刪除分類表中指定分類ID的記錄

 

 

public void demo03() throws Exception { // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root"); // 3得到預處理對象
        String sql = "delete from sort where sid=?"; PreparedStatement stat = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數
        stat.setInt(1, 1);      // 5執行SQL語句
        int line = stat.executeUpdate(); System.out.println("刪除記錄數:" + line); // 6釋放資源
 stat.close(); conn.close(); }

 

1.8 處理對象executeQuery方法

 

 

經過預處理對象的executeQuery方法,完成記錄的select語句的執行。操做格式統一以下:

 

1. 註冊驅動

 

2. 獲取鏈接

 

3. 獲取預處理對象

 

4. SQL語句佔位符設置實際參數

 

5. 執行SQL語句

 

6. 處理結果集(遍歷結果集合)

 

7. 釋放資源

 

 

1.8.1 查詢記錄:select

 

 

實現查詢分類表全部記錄

 

 

public void demo04() throws Exception { // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root"); // 3得到預處理對象
        String sql = "select * from sort"; PreparedStatement stat = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數    // 5執行SQL語句
        ResultSet rs = stat.executeQuery(); // 6處理結果集(遍歷結果集合)
        while( rs.next() ){ //獲取當前行的分類ID
            String sid = rs.getString("sid");//方法參數爲數據庫表中的列名 //獲取當前行的分類名稱
            String sname = rs.getString("sname"); //顯示數據
            System.out.println(sid+"-----"+sname); } // 7釋放資源
 rs.close(); stat.close(); conn.close(); }

 

實現查詢分類表中指定分類名稱的記錄

 

 

public void demo05() throws Exception { // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root"); // 3得到預處理對象
        String sql = "select * from sort where sname=?"; PreparedStatement stat = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數
        stat.setString(1, "奢侈品");      // 5執行SQL語句
        ResultSet rs = stat.executeQuery(); // 6處理結果集(遍歷結果集合)
        while( rs.next() ){ //獲取當前行的分類ID
            String sid = rs.getString("sid");//方法參數爲數據庫表中的列名 //獲取當前行的分類名稱
            String sname = rs.getString("sname"); //顯示數據
            System.out.println(sid+"-----"+sname); } // 7釋放資源
 rs.close(); stat.close(); conn.close(); }

 

1.9 JDBC工具類

「得到數據庫鏈接」操做,將在之後的增刪改查全部功能中都存在,能夠封裝工具類JDBCUtils。提供獲取鏈接對象的方法,從而達到代碼的重複利用。

該工具類提供方法:public static Connection getConn ()。代碼以下:

/* * JDBC工具類 */
public class JDBCUtils { public static final  String DRIVERNAME = "com.mysql.jdbc.Driver"; public static final  String URL = "jdbc:mysql://localhost:3306/mydb"; public static final  String USER = "root"; public static final  String PASSWORD = "root"; static { try { Class.forName(DRIVERNAME); } catch (ClassNotFoundException e) { System.out.println("數據庫驅動註冊失敗!"); } } //提供獲取鏈接的方法
    public static Connection getConn() throws Exception { // 2. 得到鏈接
        Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); // 返回鏈接
        return conn; } }

2. properties配置文件

2.1 使用properties配置文件

開發中得到鏈接的4個參數(驅動、URL、用戶名、密碼)一般都存在配置文件中,方便後期維護,程序若是須要更換數據庫,只須要修改配置文件便可。

一般狀況下,咱們習慣使用properties文件,此文件咱們將作以下要求:

1. 文件位置:任意,建議src

2. 文件名稱:任意,擴展名爲properties

3. 文件內容:一行一組數據,格式是key=value.

a) key命名自定義,若是是多個單詞,習慣使用點分隔。例如:jdbc.driver

b) value值不支持中文,若是須要使用非英文字符,將進行unicode轉換。

2.2 建立配置文件

在項目跟目錄下,建立文件,輸入db.properties」文件名。

文件中的內容

driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mydb
user=root password=root

2.3 加載配置文件:Properties對象

對應properties文件處理,開發中也使用Properties對象進行。咱們將採用加載properties文件得到流,而後使用Properties對象進行處理。

JDBCUtils.java中編寫代碼

public class JDBCUtils { private static String driver; private static String url; private static String user; private static String password; // 靜態代碼塊
    static { try { // 1 使用Properties處理流 // 使用load()方法加載指定的流
            Properties props = new Properties(); Reader is = new FileReader("db.properties"); props.load(is); // 2 使用getProperty(key),經過key得到須要的值,
            driver = props.getProperty("driver"); url = props.getProperty("url"); user = props.getProperty("user"); password = props.getProperty("password"); } catch (Exception e) { throw new RuntimeException(e); } } /** * 得到鏈接 */
    public static Connection getConnection() { try { // 1 註冊驅動
 Class.forName(driver); // 2 得到鏈接
            Connection conn = DriverManager.getConnection(url, user, password); return conn; } catch (Exception e) { throw new RuntimeException(e); } } }

2.4 使用JDBCUtils工具類

測試類

public class Demo { @Test public void insert(){ try{ //1,獲取鏈接對象
            Connection conn = JDBCUtils.getConnection(); //2,指定要執行的SQL語句
            String sql = "INSERT INTO zhangwu(name,money,parent) VALUES(?,?,?)"; //4,獲取SQL語句的執行對象 PreparedStatement
            PreparedStatement ppstat = conn.prepareStatement(sql); //5,執行SQL語句
            ppstat.setString(1, "股票收入"); ppstat.setDouble(2, 5000); ppstat.setString(3, "收入"); int line = ppstat.executeUpdate(); //6,處理結果集
            System.out.println("line=" + line); //7,關閉鏈接
 ppstat.close(); conn.close(); } catch(SQLException e){ throw new RuntimeException(e); } } }
相關文章
相關標籤/搜索