最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JDBC基礎(chǔ)教程

 更新時(shí)間:2014年12月09日 14:46:02   投稿:shichen2014  
這篇文章主要介紹了JDBC基礎(chǔ)知識(shí)與操作技巧,講述原理與基本技巧的基礎(chǔ)上分析了安全問題與操作注意事項(xiàng),非常具有實(shí)用價(jià)值,需要的朋友可以參考下

本文實(shí)例講述了JDBC基礎(chǔ)知識(shí)與技巧。分享給大家供大家參考。具體分析如下:

1.什么是JDBC?

通俗來講JDBC技術(shù)就是通過java程序來發(fā)送SQL語句到數(shù)據(jù)庫,數(shù)據(jù)庫收到SQL語句后執(zhí)行,把結(jié)果返回給java程序管理。

2.使用JDBC要有什么條件呢?

A)目標(biāo)數(shù)據(jù)庫主機(jī)的地址

B)數(shù)據(jù)庫軟件在該主機(jī)上所占用的端口號(hào)

C)登陸數(shù)據(jù)庫用的用戶名

D)該用戶名的密碼

E)連接數(shù)據(jù)庫

3.JDBC技術(shù)的原理

我們知道,數(shù)據(jù)庫是有各種類型的,不同的廠商生產(chǎn)的數(shù)據(jù)庫標(biāo)格和規(guī)范是不同的,這時(shí)候,如果我們用JAVA代碼來發(fā)送SQL語句,就要根據(jù)不同的數(shù)據(jù)庫來寫一套又一套的操作代碼,這對(duì)程序開發(fā)者的開發(fā)成本是十分巨大的,所以,SUN公司在開發(fā)JDBC技術(shù)的時(shí)候,規(guī)定了一套標(biāo)準(zhǔn)接口,數(shù)據(jù)庫產(chǎn)商都必須提供一個(gè)驅(qū)動(dòng)來實(shí)現(xiàn)這套接口,那么,只要程序開發(fā)者在開發(fā)時(shí)使用了該數(shù)據(jù)庫的驅(qū)動(dòng),就用一致的方法來開發(fā)了,而不需自己寫一套有一套的代碼去適應(yīng)不同的數(shù)據(jù)庫。

4.JDBC中的核心API

|- Driver : 驅(qū)動(dòng)程序類實(shí)現(xiàn)的接口。

  |-Connection connect(String url, Properties info)  --用于連接數(shù)據(jù)庫,得到連接對(duì)象

Properties 里需要設(shè)置的參數(shù):

    url: 數(shù)據(jù)庫連接的URL字符串。協(xié)議+數(shù)據(jù)庫子協(xié)議+主機(jī)+端口+數(shù)據(jù)庫

    user: 數(shù)據(jù)庫用戶名

    password: 用戶的密碼

  |-Connection :    與數(shù)據(jù)庫連接的接口

      |- Statement createStatement()   --創(chuàng)建Statement對(duì)象,用于發(fā)送sql語句

      |- PreparedStatement prepareStatement(String sql)  -創(chuàng)建PreparedStatement對(duì)象,用于發(fā)送預(yù)編譯的sql語句

      |-CallableStatement prepareCall(String sql)  --創(chuàng)建CallableStatement對(duì)象,用于調(diào)用存儲(chǔ)過程。

      |-Statement: 用于執(zhí)行靜態(tài)sql語句

          |-int executeUpdate(String sql)  --執(zhí)行更新操作(DDL+DML)

          |-ResultSet executeQuery(String sql)  --執(zhí)行查詢操作(DQL)

      |- PreparedStatement: 用于執(zhí)行預(yù)編譯的sql語句

          |- int executeUpdate() -- 執(zhí)行更新操作

          |- ResultSet executeQuery()    -- 執(zhí)行查詢操作

      |- CallableStatement: 用于執(zhí)行存儲(chǔ)過程的sql

          |- ResultSet executeQuery()  --調(diào)用存儲(chǔ)過程

          |- ResultSet: 結(jié)果集。用于封裝數(shù)據(jù)庫的查詢后的數(shù)據(jù)

              |- boolean next() --將記錄光標(biāo)移動(dòng)到下一行

              |- Object getObject(int columnIndex) -- 得到字段上的值

了解完又哪些API,下面我們就來使用JDBC發(fā)送SQL語句吧~

5.使用Statement對(duì)象操作數(shù)據(jù)庫

DDL與DML操作

步驟1

導(dǎo)包,因?yàn)槲沂褂玫氖荕ySQL數(shù)據(jù)庫,所以要使用JDBC技術(shù),必須使用由MySQL數(shù)據(jù)庫產(chǎn)商提供的數(shù)據(jù)庫驅(qū)動(dòng),所以,第一步我們要把數(shù)據(jù)庫驅(qū)動(dòng)包導(dǎo)入工程里。

使用的包名:mysql-connector-java-5.1.7-bin.jar

步驟2

創(chuàng)建一個(gè)普通的類,在里面添加一個(gè)方法,在該方法中按照以下步驟

復(fù)制代碼 代碼如下:
//URL
    private String url = "jdbc:mysql://localhost:3306/vmaxtam";
    //user
    private String user = "root";
    //password
    private String password = "root";

public void testDDL()throws Exception{
        //1.注冊(cè)驅(qū)動(dòng)
        Class.forName("com.mysql.jdbc.Driver");
       
        //2.獲取連接
        Connection conn = DriverManager.getConnection(url, user, password);
       
        //3.創(chuàng)建Statement對(duì)象
        Statement stmt = conn.createStatement();
       
        //4.準(zhǔn)備sql語句
        String sql  ="CREATE TABLE student(sid INT PRIMARY KEY,sname VARCHAR(20),age INT)";
       
        //5.通過statement對(duì)象發(fā)送sql語句,返回執(zhí)行結(jié)果
        int count = stmt.executeUpdate(sql);
       
        //6.打印執(zhí)行結(jié)果
        System.out.println("影響了"+count+"條記錄");
}
//7.關(guān)閉資源
if(statement!=null)
{
    statement.close();
}

if(conn!=null)
{
    conn.close();
}


如果要進(jìn)行DQL與DDL操作,都可以把SQL語句寫好,然后調(diào)用statement的executlUpdate方法來給數(shù)據(jù)庫執(zhí)行SQL語句,這個(gè)方法返回一個(gè)整數(shù)值,表示數(shù)據(jù)庫中有多少行受到了影響。

如果我們不改變上述的程序,想要再向數(shù)據(jù)庫發(fā)出SQL語句,那么又要寫一個(gè)程序來再次連接,操作完后又要關(guān)閉statement對(duì)象 和connection對(duì)象,這是十分繁瑣的。所以,我們一般把連接過程和釋放對(duì)象的過程抽取到一個(gè)工具類中。工具類中的代碼如下:

復(fù)制代碼 代碼如下:
public class sqlUtil {
    private static String url = "jdbc:mysql://localhost:3306/vmaxtam";
    private static String user = "root";
    private static String password = "root";

    // 獲取連接
    public static Connection getconnection() {
        Connection conn = null;
        try {
            // 1.注冊(cè)驅(qū)動(dòng)
            Class.forName("com.mysql.jdbc.Driver");
            // 2.獲取連接
            conn = DriverManager.getConnection(url, user, password);
            // 3.獲得statement對(duì)象
            Statement statement = conn.createStatement();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return conn;
    }

    // 7.關(guān)閉資源
    public static void close(Statement statement, Connection connection) {
        {
            try {
                if (statement != null)
                    statement.close();
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

還要考慮的情況就是:

一)一個(gè)用戶只需要注冊(cè)一次驅(qū)動(dòng)就行,不用每次連接數(shù)據(jù)庫都注冊(cè)驅(qū)動(dòng),所以我們把注冊(cè)驅(qū)動(dòng)的過程寫在靜態(tài)代碼塊中。

二)url 和用戶名,密碼還有驅(qū)動(dòng)類名,在程序里是寫死的,為了能夠在不改代碼的前提下更換數(shù)據(jù)庫 或者更換用戶,我們通常把這些信息寫到一份配置文件中。

配置文件寫在工程的src目錄下,名為db.properties

復(fù)制代碼 代碼如下:
url=jdbc:mysql://localhost:3306/vmaxtam
user=root
password=root
driverClass=com.mysql.jdbc.Drive

然后再sqlUtil中讀取該配置文件,最后優(yōu)化成下面代碼
復(fù)制代碼 代碼如下:
public class sqlUtil {
    private static String url = null;
    private static String user = null;
    private static String password = null;
    private static String driverClass= null;

    static{
        try {
            //1.獲得字節(jié)碼對(duì)象
            Class clazz = sqlUtil.class;
           
            //2.調(diào)用getResourceAsStream獲取路徑
            InputStream inputStream = clazz.getResourceAsStream("/db.properties");
            Properties pro = new Properties();
            pro.load(inputStream);
           
            //3.讀取參數(shù)
            url=pro.getProperty("url");
            password=pro.getProperty("password");
            user=pro.getProperty("user");
            driverClass=pro.getProperty("driverClass");
           
            Class.forName(driverClass);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("注冊(cè)失??!" + e.getMessage());
            throw new RuntimeException(e);
        }
    }
   
    // 獲取連接
    public static Connection getconnection() {
        Connection conn = null;
        try {       
            // 獲取連接
            conn = DriverManager.getConnection(url, user, password);
            // 獲得statement對(duì)象
            Statement statement = conn.createStatement();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }

    // 關(guān)閉資源
    public static void close(Statement statement, Connection connection) {
        {
            try {
                if (statement != null)
                    statement.close();
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

DQL操作

那么如何用JDBC來查詢數(shù)據(jù)庫中的數(shù)據(jù)呢?

復(fù)制代碼 代碼如下:
@Test
    public void testdsl() throws Exception {
        //獲取連接
        cnn2=sqlUtil.getconnection();
        Statement statement = cnn2.createStatement();
   
       
        //準(zhǔn)備SQL語句
        String sql = "select * from subject";
       
        //調(diào)用executeQuery執(zhí)行查詢語句
        ResultSet res = statement.executeQuery(sql);
       
        //查詢結(jié)束后res會(huì)指向表頭,想要獲取數(shù)據(jù)必須不斷地指向查詢結(jié)果的下一行,當(dāng)沒有下一行數(shù)據(jù)時(shí),返回0.
        while(res.next())
        {
            //獲取查詢結(jié)果中字段為“sjid”的值,并且要明確類型
            int id = res.getInt("sjid");
           
            //獲取查詢結(jié)果中字段為“sjname”的值,并且要明確類型
            String name = res.getString("sjname");
            System.out.println("ID:" + id + "  NAME:" + name);
        }
        sqlUtil.close(statement, cnn2);
}

以上就是使用Statement對(duì)象來操作數(shù)據(jù)庫了~

6.使用PreparedStatement操作數(shù)據(jù)庫

PreparedStatement對(duì)象其實(shí)就是一個(gè)特殊的Statement對(duì)象,它能夠預(yù)編譯SQL語句,當(dāng)你把參數(shù)設(shè)置好,然后就可以去執(zhí)行SQL語句了~

DDL與DML操作

復(fù)制代碼 代碼如下:
package com.vmaxtam.sqltest;

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

import org.junit.Test;

public class PreparedStatementTest {
    Connection connection = null;
    @Test
    public void ddldmlTest() throws Exception {
        // 1.獲取連接
        connection = sqlUtil.getconnection();

        // 2.準(zhǔn)備SQL語句,預(yù)編譯語句,參數(shù)用?號(hào)占位
        String sql = "INSERT INTO SUBJECT VALUES(?,?)";

        // 3.獲得對(duì)象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        /*
         * 4.設(shè)置SQL參數(shù) 需要參數(shù)是第幾個(gè),并且知道它的類型 下面第一句表示:SQL語句第一個(gè)參數(shù)是int類型,參數(shù)值設(shè)置為3,如此類推
         */
        preparedStatement.setInt(1, 3);
        preparedStatement.setString(2, "英語");

        // 5.交給數(shù)據(jù)庫執(zhí)行SQL
        int num = preparedStatement.executeUpdate();

        System.out.println("有" + num + "條記錄受到了影響");

              sqlUtil.close(preparedStatement , connection );
    }
}

以上就是使用PreparedStatement對(duì)象來進(jìn)行插入語句的發(fā)送,同理,DDL與DML類的語句都可以根據(jù)這樣來發(fā)送.

PreparedStatement預(yù)編譯的好處:

PreparedStatement的預(yù)編譯可以使你可以通過設(shè)置不同的參數(shù)來查詢不同的目標(biāo),在數(shù)據(jù)庫端,只會(huì)保存一段預(yù)編譯語句,但是如果你使用Statement來發(fā)送語句,每發(fā)送一條,數(shù)據(jù)庫中就會(huì)存一條,這可能會(huì)造成占用大量?jī)?nèi)存。

DQL操作

復(fù)制代碼 代碼如下:
@Test
    public void dqlTest() throws Exception {
        // 1.獲取連接
        connection = sqlUtil.getconnection();

        // 2.準(zhǔn)備SQL語句,預(yù)編譯語句,參數(shù)用?號(hào)占位
        String sql = "select * from subject where sjid=? or sjname=?";

        // 3.獲得對(duì)象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        /*
         * 4.設(shè)置SQL參數(shù) 需要參數(shù)是第幾個(gè),并且知道它的類型 下面第一句表示:SQL語句第一個(gè)參數(shù)是int類型,參數(shù)值設(shè)置為3,如此類推
         */
        preparedStatement.setInt(1, 2);
        preparedStatement.setString(2, "語文");

        // 5.交給數(shù)據(jù)庫執(zhí)行SQL
        ResultSet rst = preparedStatement.executeQuery();
       
        //6.迭代結(jié)果集
        while(rst.next())
        {
            int id = rst.getInt("sjid");
            String name = rst.getString("sjname");
            System.out.println("ID:" + id + "  NAME:" + name);
        }
       
        //7.關(guān)閉連接
        sqlUtil.close(preparedStatement, connection);
}

也是調(diào)用executeQuery();方法即可,得到結(jié)果集后迭代輸出~

既然Statement 與 PreparedStatement那么相似,比較它們的優(yōu)缺點(diǎn)吧~

Statement 與 PreparedStatement的區(qū)別:

1.語法不同

Statement只支持靜態(tài)編譯,SQL語句是寫死的。

PreparedStatement支持預(yù)編譯,用?號(hào)來占位。

2.效率不同

Statement每次都要發(fā)送一條SQL語句,不支持緩存,執(zhí)行效率低。

PreparedStatement支持預(yù)編譯,緩存在數(shù)據(jù)庫,只需發(fā)送參數(shù),執(zhí)行效率快。

3.安全性不同

Statement容易被注入。

注入:狡猾的分子可以編寫特殊的SQL語句來入侵?jǐn)?shù)據(jù)庫。

例如:要查詢某個(gè)用戶的信息

一般情況:SELECT * FROM user_list where username=xxx and password=xxx;(這里的xxx本應(yīng)為用戶填寫自己的用戶名和密碼)

注入情況:SELECT * FROM user_list where username='abc' or 1=1 -- password=xxx;

這樣1=1恒等,而且在password前加上了“--”號(hào),后面的內(nèi)容成為了注釋不被執(zhí)行。也就是說,這樣就能不用密碼地查詢所有的用戶信息。

PreparedStatement,因?yàn)橐?guī)定了SQL語句中的參數(shù),所以可以防止注入。

結(jié)論:建議使用PreparedStatement,因?yàn)樗旄踩?/strong>。

7.使用CallableStatement執(zhí)行存儲(chǔ)過程

使用CallableStatement只是執(zhí)行存儲(chǔ)過程,創(chuàng)建存儲(chǔ)過程我們還是要在數(shù)據(jù)庫內(nèi)創(chuàng)建的。

步驟1

現(xiàn)在數(shù)據(jù)庫建好一個(gè)存儲(chǔ)過程:

復(fù)制代碼 代碼如下:
DELIMITER $
CREATE PROCEDURE pro_add(IN a INT , IN b VARCHAR(20),OUT c INT)
BEGIN   
    SELECT * FROM SUBJECT WHERE sjid=a OR sjname=b;
    SET c=a+a+a+a;
END $

步驟2

利用java代碼執(zhí)行,并得到輸出參數(shù)

復(fù)制代碼 代碼如下:
@Test
public void calaST() throws Exception {
        //獲取連接
        connection= sqlUtil.getconnection();
        //準(zhǔn)備SQL語句
        String sql = "CALL pro_add(?,?,?)";
       
        //得到callableStatement對(duì)象
        CallableStatement cbs = connection.prepareCall(sql);
       
        //設(shè)置輸入?yún)?shù),和preparedStatement一樣
        cbs.setInt(1, 3);
        cbs.setString(2, "數(shù)學(xué)");
       
        /*那么如何設(shè)置輸出參數(shù)呢?
         * 需要注冊(cè)輸出參數(shù)!
         */
        cbs.registerOutParameter(3, java.sql.Types.INTEGER);//需要使用內(nèi)置對(duì)象來設(shè)置參數(shù)類型
       
        //執(zhí)行SQL語句
        cbs.executeQuery();
       
        //利用getXXX方法得到相應(yīng)位置的輸出參數(shù)
        Integer num= cbs.getInt(3);
       
        System.out.println("a*4 is " + num);
       
             //關(guān)閉資源
        sqlUtil.close(cbs, connection);
}

希望本文所述對(duì)大家的Java程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Java中報(bào)錯(cuò)org.springframework.jdbc.UncategorizedSQLException的多種解決方法

    Java中報(bào)錯(cuò)org.springframework.jdbc.UncategorizedSQLException的多種

    本文主要介紹了Java中報(bào)錯(cuò)org.springframework.jdbc.UncategorizedSQLException的多種解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 詳解java實(shí)現(xiàn)HTTP請(qǐng)求的三種方式

    詳解java實(shí)現(xiàn)HTTP請(qǐng)求的三種方式

    這篇文章主要介紹了java實(shí)現(xiàn)HTTP請(qǐng)求的三種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • java多線程編程之使用thread類創(chuàng)建線程

    java多線程編程之使用thread類創(chuàng)建線程

    在Java中創(chuàng)建線程有兩種方法:使用Thread類和使用Runnable接口。在使用Runnable接口時(shí)需要建立一個(gè)Thread實(shí)例
    2014-01-01
  • MyBatis插入Insert、InsertSelective的區(qū)別及使用心得

    MyBatis插入Insert、InsertSelective的區(qū)別及使用心得

    這篇文章主要介紹了MyBatis插入Insert、InsertSelective的區(qū)別及使用心得,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java操作mongodb示例分享

    java操作mongodb示例分享

    這篇文章主要介紹了java操作mongodb示例,實(shí)現(xiàn)了簡(jiǎn)單的條件查詢和復(fù)雜的條件查詢,需要的朋友可以參考下
    2014-02-02
  • 詳解Java數(shù)字簽名提供XML安全

    詳解Java數(shù)字簽名提供XML安全

    在本篇文章中我們給大家整理了關(guān)于Java數(shù)字簽名提供XML安全的知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2018-08-08
  • PowerJob的TransportServiceAware工作流程源碼解讀

    PowerJob的TransportServiceAware工作流程源碼解讀

    這篇文章主要介紹了PowerJob的TransportServiceAware工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Java常用排序算法及性能測(cè)試集合

    Java常用排序算法及性能測(cè)試集合

    周末天氣不好,在家無事,把常用排序算法理了一遍,收獲不小,特寫文章紀(jì)念。這些算法在學(xué)校的時(shí)候?qū)W過一遍,很多原理都忘記了
    2013-06-06
  • Java模擬微信來電提醒示例

    Java模擬微信來電提醒示例

    這篇文章主要為大家介紹了Java模擬微信來電提醒示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Java線程同步問題--哲學(xué)家就餐

    Java線程同步問題--哲學(xué)家就餐

    這篇文章主要介紹了Java線程同步問題,線程的同步是保證多線程安全訪問競(jìng)爭(zhēng)資源的一種手段。線程的同步是Java多線程編程的難點(diǎn),下面文章舉例的方式講解Java線程同步,具有一定的參考價(jià)值,需要的朋友可以參考下
    2022-02-02

最新評(píng)論

凉城县| 随州市| 沙坪坝区| 宜阳县| 台中市| 南昌市| 句容市| 烟台市| 甘孜县| 郁南县| 禹城市| 洪泽县| 石柱| 山阴县| 康马县| 永州市| 高淳县| 临西县| 海晏县| 林州市| 红桥区| 监利县| 明星| 桂阳县| 疏勒县| 商城县| 登封市| 皮山县| 安陆市| 定日县| 康平县| 仁布县| 清苑县| 双峰县| 札达县| 长海县| 枣阳市| 渭南市| 青岛市| 叶城县| 吉木萨尔县|