JDBC筆記(1)

JDBC筆記(1)

jdbc介紹

JDBC 是 Java 訪問數(shù)據(jù)庫的標準規(guī)范,真正怎么操作數(shù)據(jù)庫還需要具體的實現(xiàn)類轮蜕,也就是數(shù)據(jù)庫驅(qū)動。每個數(shù)據(jù)庫廠商根據(jù)自家數(shù)據(jù)庫的通信格式編寫好自己數(shù)據(jù)庫的驅(qū)動。所以我們只需要會調(diào)用JDBC 接口中的方法即可削解,數(shù)據(jù)庫驅(qū)動由數(shù)據(jù)庫廠商提供营勤。
使用 JDBC 的好處:

  1. 程序員如果要開發(fā)訪問數(shù)據(jù)庫的程序灵嫌,只需要會調(diào)用 JDBC 接口中的方法即可壹罚,不用關注類是如何實現(xiàn)的。
  2. 使用同一套 Java 代碼寿羞,進行少量的修改就可以訪問其他 JDBC 支持的數(shù)據(jù)庫

jdbc簡單入門

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
* 步驟:
            1. 導入驅(qū)動jar包 mysql-connector-java-5.1.37-bin.jar
                1.復制mysql-connector-java-5.1.37-bin.jar到項目的libs目錄下
                2.右鍵-->Add As Library
            2. 注冊驅(qū)動
            3. 獲取數(shù)據(jù)庫連接對象 Connection
            4. 定義sql
            5. 獲取執(zhí)行sql語句的對象 Statement
            6. 執(zhí)行sql猖凛,接受返回結果
            7. 處理結果
            8. 釋放資源
public class JdbcDemo01 {
    public static void main(String[] args) throws Exception {
        //1.導入jar包  建立lib目錄
        //2.注冊驅(qū)動  Class.forName(數(shù)據(jù)庫驅(qū)動實現(xiàn)類) 加載和注冊數(shù)據(jù)庫驅(qū)動,數(shù)據(jù)庫驅(qū)動由 mysql 廠商
         //         "com.mysql.jdbc.Driver"  jdk3.0后可以不寫
        Class.forName("com.mysql.jdbc.Driver");
        //3.獲取數(shù)據(jù)庫連接對象     協(xié)議名:子協(xié)議://服務器名或 IP 地址:端口號/數(shù)據(jù)庫名?參數(shù)=參數(shù)值
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db4", "root", "root");
        //4.定義sql語句
        String sql = "update stu2 set age = 50 where id=1";
        //5.獲取執(zhí)行sql的對象Statement
        Statement stat = conn.createStatement();
        //6.執(zhí)行sql
        int i = stat.executeUpdate(sql);
        //7.處理結果
        System.out.println(i);
        //8.釋放資源
        stat.close();
        conn.close();
    }
}

jdbc案例:實現(xiàn)登錄

工具類:連接方法绪穆,釋放資源方法

package cn.itcast.util;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class JdbsUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    static {

        try {
            //1.創(chuàng)建properties集合類
            Properties pro = new Properties();
            //2.獲取src路徑下文件的位置辨泳,用ClassLoader類加載器
            ClassLoader classLoader = JdbsUtils.class.getClassLoader();
            URL res = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            //3.加載文件
            pro.load(new FileReader(path));
            //4.獲取數(shù)據(jù),賦值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //5.注冊驅(qū)動
            Class.forName(driver);

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

    }



    public static Connection getConnection() throws SQLException {

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

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

    }

    public static void close(Statement stat, Connection conn, ResultSet rs){
        if(stat != null){
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs!= null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }

}

配置文件jdbc.properties

url = jdbc:mysql:///db4
user = root
password = root
driver = com.mysql.jdbc.Driver

測試類

login沒使用 PreparedStatement 接口玖院,可以sql注入

login2使用了 PreparedStatement 接口

PreparedStatement 是 Statement 接口的子接口菠红,繼承于父接口中所有的方法。它是一個預編譯的 SQL 語句

PreparedSatement 的好處

  1. prepareStatement()會先將 SQL 語句發(fā)送給數(shù)據(jù)庫預編譯难菌。PreparedStatement 會引用著預編譯后的結果试溯。
    可以多次傳入不同的參數(shù)給 PreparedStatement 對象并執(zhí)行。減少 SQL 編譯次數(shù)郊酒,提高效率遇绞。
  2. 安全性更高,沒有 SQL 注入的隱患燎窘。
  3. 提高了程序的可讀性

使用 PreparedStatement 的步驟:

  1. 編寫 SQL 語句摹闽,未知內(nèi)容使用?占位:"SELECT * FROM user WHERE name=? AND password=?";
  2. 獲得 PreparedStatement 對象
  3. 設置實際參數(shù):setXxx(占位符的位置, 真實的值)
  4. 執(zhí)行參數(shù)化 SQL 語句
  5. 關閉資源
package cn.itcast.jdbc;

import cn.itcast.util.JdbsUtils;

import java.sql.*;
import java.util.Scanner;

public class JdbcDemoUserLogin {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入用戶名");
        String username = sc.nextLine();
        System.out.println("請輸入密碼");
        String password = sc.nextLine();
        boolean flg = new JdbcDemoUserLogin().login2(username, password);
        if (flg){
            System.out.println("登錄成功");
        }else {
            System.out.println("用戶名或密碼錯誤");
        }


    }
    public boolean login(String username,String password){
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        if(username==null || password == null){
            return false;
        }
        try {
            conn = JdbsUtils.getConnection();
            stat = conn.createStatement();
            String sql = "select *from user where username = '"+username+"' and password = '"+password+"'";
            rs = stat.executeQuery(sql);
            /*if (rs.next()){
                return true;
            }
            else {
                return false;
            }*/
            return rs.next();

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbsUtils.close(stat,conn,rs);
        }

        return false;
    }


    public boolean login2(String username,String password){
        Connection conn = null;
        PreparedStatement pstat = null;
        ResultSet rs = null;
        if(username==null || password == null){
            return false;
        }
        try {
            conn = JdbsUtils.getConnection();

            String sql = "select *from user where username = ? and password = ?";
            pstat = conn.prepareStatement(sql);
            pstat.setString(1,username);
            pstat.setString(2,password);
            rs = pstat.executeQuery();
            /*if (rs.next()){
                return true;
            }
            else {
                return false;
            }*/
            return rs.next();

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbsUtils.close(pstat,conn,rs);
        }

        return false;
    }
}

jdbc事務處理

使用了JdbcUtils工具類

Connection 接口中與事務有關的方法

void setAutoCommit(boolean autoCommit) 參數(shù)是 true 或 false 如果設置為 false,表示關閉自動提交荠耽,相當于開啟事務

void commit() 提交事務

void rollback() 回滾事務

開發(fā)步驟

1) 獲取連接
2) 開啟事務
3) 獲取到 PreparedStatement
4) 使用 PreparedStatement 執(zhí)行兩次更新操作
5) 正常情況下提交事務
6) 出現(xiàn)異彻澈В回滾事務
7) 最后關閉資源
package cn.itcast.jdbc;

import cn.itcast.util.JdbsUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JdbcDemo06 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstat1 = null;
        PreparedStatement pstat2 = null;
        try {
            conn = JdbsUtils.getConnection();
            //開啟事務
            conn.setAutoCommit(false);
            String sql1 = "update shuzhi set num = num-? where id = ?";
            String sql2 = "update shuzhi set num = num+? where id = ?";

            pstat1 = conn.prepareStatement(sql1);
            pstat2 = conn.prepareStatement(sql2);

            pstat1.setInt(1,500);//表示sql1第1個問號所代表得數(shù)值
            pstat1.setInt(2,1);//表示sql2第2個問號所代表得數(shù)值
            pstat2.setInt(1,500);
            pstat2.setInt(2,4);
            
            pstat1.executeUpdate();
            pstat2.executeUpdate();
            //提交事務
            conn.commit();
        } catch (Exception e) {
            try {
                //事務回滾
                conn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JdbsUtils.close(pstat1,conn);
            JdbsUtils.close(pstat2,conn);
        }

    }
}

***詳解各個對象:

    1. DriverManager:驅(qū)動管理對象
        * 功能:
            1. 注冊驅(qū)動:告訴程序該使用哪一個數(shù)據(jù)庫驅(qū)動jar
                static void registerDriver(Driver driver) :注冊與給定的驅(qū)動程序 DriverManager 。 
                寫代碼使用:  Class.forName("com.mysql.jdbc.Driver");
                通過查看源碼發(fā)現(xiàn):在com.mysql.jdbc.Driver類中存在靜態(tài)代碼塊
                 static {
                        try {
                            java.sql.DriverManager.registerDriver(new Driver());
                        } catch (SQLException E) {
                            throw new RuntimeException("Can't register driver!");
                        }
                    }

                注意:mysql5之后的驅(qū)動jar包可以省略注冊驅(qū)動的步驟铝量。
            2. 獲取數(shù)據(jù)庫連接:
                * 方法:static Connection getConnection(String url, String user, String password) 
                * 參數(shù):
                    * url:指定連接的路徑
                        * 語法:jdbc:mysql://ip地址(域名):端口號/數(shù)據(jù)庫名稱
                        * 例子:jdbc:mysql://localhost:3306/db3
                        * 細節(jié):如果連接的是本機mysql服務器倘屹,并且mysql服務默認端口是3306,則url可以簡寫為:jdbc:mysql:///數(shù)據(jù)庫名稱
                    * user:用戶名
                    * password:密碼 
    2. Connection:數(shù)據(jù)庫連接對象
        1. 功能:
            1. 獲取執(zhí)行sql 的對象
                * Statement createStatement()
                * PreparedStatement prepareStatement(String sql)  
            2. 管理事務:
                * 開啟事務:setAutoCommit(boolean autoCommit) :調(diào)用該方法設置參數(shù)為false慢叨,即開啟事務
                * 提交事務:commit() 
                * 回滾事務:rollback() 
    3. Statement:執(zhí)行sql的對象
        1. 執(zhí)行sql
            1. boolean execute(String sql) :可以執(zhí)行任意的sql 了解 
            2. int executeUpdate(String sql) :執(zhí)行DML(insert纽匙、update、delete)語句拍谐、DDL(create烛缔,alter、drop)語句
                * 返回值:影響的行數(shù)轩拨,可以通過這個影響的行數(shù)判斷DML語句是否執(zhí)行成功 返回值>0的則執(zhí)行成功践瓷,反之,則失敗亡蓉。
            3. ResultSet executeQuery(String sql)  :執(zhí)行DQL(select)語句
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晕翠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淋肾,老刑警劉巖硫麻,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異樊卓,居然都是意外死亡拿愧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進店門碌尔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浇辜,“玉大人,你說我怎么就攤上這事七扰∩萋福” “怎么了?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵颈走,是天一觀的道長膳灶。 經(jīng)常有香客問我,道長立由,這世上最難降的妖魔是什么轧钓? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮锐膜,結果婚禮上毕箍,老公的妹妹穿的比我還像新娘。我一直安慰自己道盏,他們只是感情好而柑,可當我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著荷逞,像睡著了一般媒咳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上种远,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天涩澡,我揣著相機與錄音,去河邊找鬼坠敷。 笑死妙同,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的膝迎。 我是一名探鬼主播粥帚,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼限次!你這毒婦竟也來了芒涡?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拖陆,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懊亡,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡依啰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了店枣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片速警。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鸯两,靈堂內(nèi)的尸體忽然破棺而出闷旧,到底是詐尸還是另有隱情,我是刑警寧澤钧唐,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布忙灼,位于F島的核電站,受9級特大地震影響钝侠,放射性物質(zhì)發(fā)生泄漏该园。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一帅韧、第九天 我趴在偏房一處隱蔽的房頂上張望里初。 院中可真熱鬧,春花似錦忽舟、人聲如沸双妨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刁品。三九已至,卻和暖如春帘饶,著一層夾襖步出監(jiān)牢的瞬間哑诊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工及刻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留镀裤,地道東北人。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓缴饭,卻偏偏與公主長得像暑劝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子颗搂,可洞房花燭夜當晚...
    茶點故事閱讀 45,930評論 2 361