国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

JDBC基礎(chǔ)

2019-11-14 22:10:35
字體:
供稿:網(wǎng)友
JDBC基礎(chǔ)JDBC基礎(chǔ)

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ī)上所占用的端口號

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

D)該用戶名的密碼

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

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

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

4.JDBC中的核心API

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

  |-Connectionconnect(Stringurl,PRopertiesinfo)--用于連接數(shù)據(jù)庫,得到連接對象

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

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

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

    passWord:用戶的密碼

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

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

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

      |-CallableStatementprepareCall(Stringsql)--創(chuàng)建CallableStatement對象,用于調(diào)用存儲過程

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

          |-intexecuteUpdate(Stringsql)--執(zhí)行更新操作(DDL+DML)

          |-ResultSetexecuteQuery(Stringsql)--執(zhí)行查詢操作(DQL)

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

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

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

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

          |-ResultSetexecuteQuery()--調(diào)用存儲過程

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

              |-booleannext()--將記錄光標(biāo)移動到下一行

              |-ObjectgetObject(intcolumnIndex)--得到字段上的值

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

5.使用Statement對象操作數(shù)據(jù)庫DDL與DML操作

步驟1

導(dǎo)包,因?yàn)槲沂褂玫氖?a href="http://m.survivalescaperooms.com/article.asp?typeid=172">MySQL數(shù)據(jù)庫,所以要使用JDBC技術(shù),必須使用由MySQL數(shù)據(jù)庫產(chǎn)商提供的數(shù)據(jù)庫驅(qū)動,所以,第一步我們要把數(shù)據(jù)庫驅(qū)動包導(dǎo)入工程里。

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

步驟2

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

//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.注冊驅(qū)動        Class.forName("com.mysql.jdbc.Driver");                //2.獲取連接        Connection conn = DriverManager.getConnection(url, user, password);                //3.創(chuàng)建Statement對象        Statement stmt = conn.createStatement();                //4.準(zhǔn)備sql語句        String sql  ="CREATE TABLE student(sid INT PRIMARY KEY,sname VARCHAR(20),age INT)";                //5.通過statement對象發(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語句,這個方法返回一個整數(shù)值,表示數(shù)據(jù)庫中有多少行受到了影響。

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

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.注冊驅(qū)動            Class.forName("com.mysql.jdbc.Driver");            // 2.獲取連接            conn = DriverManager.getConnection(url, user, password);            // 3.獲得statement對象            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();            }        }    }}

還要考慮的情況就是:

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

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

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

url=jdbc:mysql://localhost:3306/vmaxtamuser=rootpassword=rootdriverClass=com.mysql.jdbc.Drive

然后再sqlUtil中讀取該配置文件,最后優(yōu)化成下面代碼

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é)碼對象            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("注冊失敗!" + e.getMessage());            throw new RuntimeException(e);        }    }            // 獲取連接    public static Connection getconnection() {        Connection conn = null;        try {                    // 獲取連接            conn = DriverManager.getConnection(url, user, password);            // 獲得statement對象            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ù)呢?

@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會指向表頭,想要獲取數(shù)據(jù)必須不斷地指向查詢結(jié)果的下一行,當(dāng)沒有下一行數(shù)據(jù)時,返回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對象來操作數(shù)據(jù)庫了~

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

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

DDL與DML操作
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ù)用?號占位        String sql = "INSERT INTO SUBJECT VALUES(?,?)";        // 3.獲得對象        PreparedStatement preparedStatement = connection.prepareStatement(sql);        /*         * 4.設(shè)置SQL參數(shù) 需要參數(shù)是第幾個,并且知道它的類型 下面第一句表示:SQL語句第一個參數(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對象來進(jìn)行插入語句的發(fā)送,同理,DDL與DML類的語句都可以根據(jù)這樣來發(fā)送.

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

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

DQL操作

@Test    public void dqlTest() throws Exception {        // 1.獲取連接        connection = sqlUtil.getconnection();        // 2.準(zhǔn)備SQL語句,預(yù)編譯語句,參數(shù)用?號占位        String sql = "select * from subject where sjid=? or sjname=?";        // 3.獲得對象        PreparedStatement preparedStatement = connection.prepareStatement(sql);        /*         * 4.設(shè)置SQL參數(shù) 需要參數(shù)是第幾個,并且知道它的類型 下面第一句表示:SQL語句第一個參數(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ù)編譯,用?號來占位。

2.效率不同

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

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

3.安全性不同

Statement容易被注入

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

例如:要查詢某個用戶的信息

一般情況:SELECT*FROMuser_listwhereusername=xxxandpassword=xxx;(這里的xxx本應(yīng)為用戶填寫自己的用戶名和密碼)

注入情況:SELECT*FROMuser_listwhereusername=’abc’or1=1--password=xxx;

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

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

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

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

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

步驟1

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

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ù)

    @Test    public void calaST() throws Exception {        //獲取連接        connection= sqlUtil.getconnection();        //準(zhǔn)備SQL語句        String sql = "CALL pro_add(?,?,?)";                //得到callableStatement對象        CallableStatement cbs = connection.prepareCall(sql);                //設(shè)置輸入?yún)?shù),和preparedStatement一樣        cbs.setInt(1, 3);        cbs.setString(2, "數(shù)學(xué)");                /*那么如何設(shè)置輸出參數(shù)呢?         * 需要注冊輸出參數(shù)!         */        cbs.registerOutParameter(3, java.sql.Types.INTEGER);//需要使用內(nèi)置對象來設(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);            }


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 将乐县| 常宁市| 女性| 罗甸县| 深泽县| 瑞安市| 滦平县| 潢川县| 盐山县| 福建省| 潞西市| 建湖县| 临夏市| 方山县| 鄂伦春自治旗| 黔江区| 遂溪县| 常德市| 兴文县| 安乡县| 海晏县| 安阳市| 东莞市| 壶关县| 郁南县| 屏山县| 乌兰县| 正镶白旗| 蕲春县| 武功县| 乌拉特中旗| 邢台市| 湘乡市| 光山县| 长春市| 奈曼旗| 葵青区| 南康市| 乌拉特前旗| 红原县| 台东市|