JDBC操作全攻略

JDBC操作全攻略

JDBC簡(jiǎn)介

JDBC(Java Database Connectivity),也稱為Java數(shù)據(jù)庫(kù)連接林艘,是Java用于連接數(shù)據(jù)庫(kù)的接口規(guī)范竹祷,需要注意的是暴凑,JDBC并沒(méi)有提供的實(shí)現(xiàn),具體的實(shí)現(xiàn)是由數(shù)據(jù)庫(kù)提供商瓮孙,比如MySQL谜疤,Oracle等負(fù)責(zé)提供,JDBC提供了一整套完整的連接規(guī)范帽撑,包括了Driver振劳,DriverManagerConnection油狂,StatementPreparedStatement,ResultSet寸癌,DatabaseMetaData专筷,ResultSetMetaDataParameterMetaData等等

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

在Java程序中蒸苇,操作數(shù)據(jù)庫(kù)時(shí)磷蛹,通常需要幾個(gè)步驟

  1. 導(dǎo)入對(duì)應(yīng)的JDBC實(shí)現(xiàn):由于JDBC本身沒(méi)有提供對(duì)應(yīng)的實(shí)現(xiàn),也不太可能提供對(duì)應(yīng)的實(shí)現(xiàn)溪烤,所以需要導(dǎo)入對(duì)應(yīng)數(shù)據(jù)庫(kù)供應(yīng)商提供的實(shí)現(xiàn)味咳,比如MySQL的實(shí)現(xiàn)
  2. 在程序中手動(dòng)注冊(cè)對(duì)應(yīng)的數(shù)據(jù)庫(kù)驅(qū)動(dòng)
  3. 建立并且打開(kāi)對(duì)應(yīng)的連接
  4. 通過(guò)連接獲取一個(gè)Statement對(duì)象,用于發(fā)送SQL檬嘀,并且獲得對(duì)應(yīng)的結(jié)果
  5. 從Statement中獲得結(jié)果集對(duì)象
  6. 關(guān)閉對(duì)應(yīng)的結(jié)果集槽驶、Statement以及連接

接下來(lái)通過(guò)代碼來(lái)具體查看如何操作

首先是導(dǎo)入MySQL的實(shí)現(xiàn),對(duì)應(yīng)的Maven依賴為


    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>

然后建立測(cè)試類TestJDBC.java

注冊(cè)MySQL驅(qū)動(dòng)


    // 注冊(cè)MySQL驅(qū)動(dòng)
    Class.forName("com.mysql.jdbc.Driver");

建立連接


    private static final String SQL_URL = "jdbc:mysql://localhost:3306/spring"; // 數(shù)據(jù)庫(kù)連接地址
    private static final String SQL_USER_NAME = "root"; // 賬號(hào)
    private static final String SQL_PASSWORD = "huanfeng"; // 密碼

    // 建立連接
    Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

    // 獲得Statment對(duì)象
    Statement statement = connection.createStatement();

完整的過(guò)程如下所示


    private static final String SQL_URL = "jdbc:mysql://localhost:3306/spring";
    private static final String SQL_USER_NAME = "root";
    private static final String SQL_PASSWORD = "huanfeng";

    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;

    try {

        // 注冊(cè)MySQL驅(qū)動(dòng)
        Class.forName("com.mysql.jdbc.Driver");

        // 建立連接
        connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        String sql = "SELECT * FROM user";
        
        // 獲得Statement
        statement = connection.createStatement();
    
        // 獲得ResultSet
        resultSet = statement.executeQuery(sql);

        // 操作ResultSet

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        // 注意關(guān)閉的順序鸳兽,應(yīng)該從ResultSet再到Statement再到Connection
        // 關(guān)閉ResultSet
        if (resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        // 關(guān)閉Statement
        if (statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        // 關(guān)閉Connection
        if (connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

這里一定要注意掂铐,資源用完之后一定要關(guān)閉,因?yàn)榻⒁粋€(gè)對(duì)應(yīng)的連接是非常消耗資源的揍异,而如果使用完之后不關(guān)閉資源全陨,會(huì)造成非常大的資源浪費(fèi),為了證實(shí)這一點(diǎn)衷掷,下面進(jìn)行一個(gè)簡(jiǎn)單的測(cè)試辱姨,測(cè)試建立一個(gè)Connection所消耗的時(shí)間


 @Test
    public void testConnection() throws ClassNotFoundException, SQLException {

        Class.forName("com.mysql.jdbc.Driver");

        long start = System.currentTimeMillis();
        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);
        long end = System.currentTimeMillis();
        connection.close();
        System.out.printf("cost time %d ms\n", (end - start));

    }

對(duì)應(yīng)的輸出結(jié)果如下所示


    cost time 360 ms

可以看到,建立一個(gè)Connection連接需要消耗非常多的時(shí)間戚嗅,原因在于雨涛,建立連接的時(shí)候枢舶,本質(zhì)上是通過(guò)驅(qū)動(dòng)程序與數(shù)據(jù)庫(kù)之間建立一個(gè)Socket連接,對(duì)于Socket有了解的朋友應(yīng)該知道镜悉,建立Socket連接是比較消耗時(shí)間的祟辟,而且維持一個(gè)Socket連接也是非常消耗資源的,所以當(dāng)資源使用完畢之后侣肄,應(yīng)該關(guān)閉對(duì)應(yīng)的資源旧困,當(dāng)然,更好的做法是使用數(shù)據(jù)庫(kù)連接池技術(shù)稼锅,將Connection對(duì)象緩存起來(lái)吼具,來(lái)避免頻繁創(chuàng)建Connection對(duì)象。

JDBC實(shí)戰(zhàn)

上面大概了解了JDBC的操作步驟以及基本的注意事項(xiàng)矩距,接下來(lái)通過(guò)一個(gè)例子來(lái)使用JDBC操作數(shù)據(jù)庫(kù)拗盒,加深對(duì)JDBC使用的了解

建立連接的過(guò)程同上,這里不重復(fù)敘述

插入數(shù)據(jù)

    @Test
    public void testInsert() throws ClassNotFoundException, SQLException {

        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        String sql = "Insert into user(id, name) value(4, 'Tom')";
        Statement statement = connection.createStatement();
        int result = statement.executeUpdate(sql);
        System.out.println(result);
        statement.close();
        connection.close();

    }

上面是最簡(jiǎn)單的插入操作锥债,不過(guò)一般來(lái)說(shuō)陡蝇,我們會(huì)插入?yún)?shù)而不是固定的數(shù)值,所以上面的內(nèi)容會(huì)變成


    int id = 4;
    String name = "Tom";
    // 拼接SQL語(yǔ)句
    String sql = "Insert into user(id, name) value("+ id +", '"+ name +"')";

通過(guò)拼接SQL語(yǔ)句哮肚,然后使用Statement來(lái)執(zhí)行語(yǔ)句是解決插入?yún)?shù)的一種方式登夫,但是,通過(guò)這種方式進(jìn)行數(shù)據(jù)庫(kù)操作會(huì)出現(xiàn)SQL注入的危險(xiǎn)允趟,比如說(shuō)恼策,當(dāng)有人把參數(shù)name的內(nèi)容填寫為 Tom'); DELETE FROM USER; --,那么此時(shí)拼接后的SQL語(yǔ)句就會(huì)變成insert into user(id, name) values(4, 'tom'); delete from user; -- 此時(shí)就非常危險(xiǎn)了潮剪,雖然這里是不會(huì)出現(xiàn)問(wèn)題的涣楷,因?yàn)閟tatement一次只能執(zhí)行一條語(yǔ)句,但是如果是查詢后面被加上這些內(nèi)容抗碰,那就非常危險(xiǎn)了狮斗。為了避免被注入的情況發(fā)生,JDBC提供了另外一種方式弧蝇,采用預(yù)編譯處理SQL情龄,然后使用PreparedStatement設(shè)置參數(shù)以及執(zhí)行對(duì)應(yīng)的SQL語(yǔ)句,如下捍壤。


    // 采用占位符來(lái)處理
    String sql = "Insert into user(id, name) value(?, ?)";

    PreparedStatement statement = connection.prepareStatement(sql);
    // 設(shè)置對(duì)應(yīng)的參數(shù)骤视,注意這里是從1開(kāi)始,不是從0開(kāi)始
    statement.setInt(1, id);
    statement.setString(2, name);
    // 這里也可以直接使用
    // statement.setObject(1, id);
    // statement.setObject(2, name);
    // 不需要指定對(duì)應(yīng)的參數(shù)類型鹃觉,將其交給JDBC進(jìn)行判斷即可

JDBC是推薦使用PreparedStatement來(lái)進(jìn)行SQL處理专酗,而不是Statement來(lái)處理,原因在于PreparedStatement提供了預(yù)處理機(jī)制盗扇,可以預(yù)防SQL注入的發(fā)送祷肯,而且由于是采用預(yù)處理機(jī)制沉填,所以PreparedStatement的執(zhí)行效率要高于Statement

刪除數(shù)據(jù)


    @Test
    public void testDelete() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        int id = 3;
        String sql = "DELETE FROM  USER where id = ?";

        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setObject(1, id);

        int result = statement.executeUpdate();

        statement.close();
        connection.close();
    }

修改數(shù)據(jù)


    @Test
    public void testUpdate() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        int id = 2;
        String name = "Jack";
        String sql = "UPDATE USER SET NAME = ? where id = ?";

        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setObject(1, name);
        statement.setObject(2, id);

        int result = statement.executeUpdate();

        statement.close();
        connection.close();
    }

查詢數(shù)據(jù)

談到查詢數(shù)據(jù),這里就有一個(gè)新的對(duì)象需要介紹佑笋,ResultSet翼闹,在JDBC中,查詢的結(jié)果一般都是以行為單位的蒋纬,可以是單行也可以是多行猎荠,JDBC將每一行都封裝成一個(gè)ResultSet對(duì)象,對(duì)于ResultSet的操作蜀备,其實(shí)就是一個(gè)迭代的過(guò)程关摇,在獲取的時(shí)候,需要通過(guò) ResultSet.getXX(ID) 或者ResultSet.getXX(CLO_NAME)來(lái)獲取對(duì)應(yīng)行的數(shù)據(jù)碾阁,然后通過(guò)ResultSet.next()將指針移動(dòng)到下一行输虱。


    @Test
    public void testQuery() throws ClassNotFoundException, SQLException {

        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        int id = 1;
        String sql = "SELECT id, name FROM USER where id = ?";

        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setObject(1, id);

        // 查詢返回的ResultSet
        ResultSet resultSet = statement.executeQuery();

        // 遍歷ResultSet
        while (resultSet.next()){
            // 取出對(duì)應(yīng)的數(shù)據(jù)
            int n_id = resultSet.getInt("id");
            String n_name = resultSet.getString("name");
            // 封裝成對(duì)應(yīng)的對(duì)象
            User user = new User(n_id, n_name);
            System.out.println("user: " + user);
        }
        // 關(guān)閉對(duì)應(yīng)的連接
        resultSet.close();
        statement.close();
        connection.close();
    }

大對(duì)象處理

所謂的大對(duì)象,指的是數(shù)據(jù)庫(kù)中定義的CLOB(Character Large Object )脂凶、BLOB(Binary Large Object)宪睹,這兩個(gè)數(shù)據(jù)類型是用于把包含信息量比較大的數(shù)據(jù)存儲(chǔ)在列中,當(dāng)做一個(gè)屬性蚕钦,其中CLOB主要是用于存放字符類型大對(duì)象横堡,比如說(shuō)一本書(shū)的內(nèi)容,BLOB主要用于存放二進(jìn)制類型的大對(duì)象冠桃,比如說(shuō)一部小電影。JDBC同樣為操作這兩種數(shù)據(jù)類型提供支持道宅,不過(guò)食听,操作起來(lái)跟普通的數(shù)據(jù)類型有所不同,具體如下所示


    @Test
    public void testBLOB() throws ClassNotFoundException, SQLException, IOException, InterruptedException {
        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        // 存入Blob類型的數(shù)據(jù)
        File file = new File("d:/img.jpg");
        int id = 121;
        String name = "jack";
        String sql = "insert into user(id, name, b_data) values(?, ?, ?)";

        PreparedStatement statement = connection.prepareStatement(sql);

        statement.setObject(1, id);
        statement.setObject(2, name);
        // 這里需要注意污茵,類型應(yīng)該為Blob樱报,直接傳一個(gè)輸入流即可
        statement.setBlob(3, new FileInputStream(file));

        int result = statement.executeUpdate();
        System.out.println(result);

        // 讀取Blob類型的數(shù)據(jù)
        sql = "SELECT b_data FROM user WHERE id = ?";
        statement = connection.prepareStatement(sql);
        statement.setObject(1, id);

        ResultSet resultSet = statement.executeQuery();

        if (resultSet.next()){
            // 注意這里,返回的類型是BLob
            Blob b_data = resultSet.getBlob("b_data");
            InputStream inputStream = b_data.getBinaryStream();
            byte[] buf = new byte[inputStream.available()];
            FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/new_img.jpg"));
            inputStream.read(buf);
            fileOutputStream.write(buf);
            fileOutputStream.flush();
            System.out.println("finish");
        }
        resultSet.close();
        statement.close();
        connection.close();
    }

CLOB的操作基本同BLOB泞当,只是對(duì)應(yīng)的類型設(shè)置為CLOB即可迹蛤,需要注意的是,在MySQL中襟士,沒(méi)有數(shù)據(jù)類型為CLOB的數(shù)據(jù)類型盗飒,其對(duì)應(yīng)的是text,這里在創(chuàng)建數(shù)據(jù)表的時(shí)候需要注意一下陋桂。

批量處理

所謂的批處理逆趣,其實(shí)就是同時(shí)指定多個(gè)SQL語(yǔ)句,通常由兩種做法嗜历,一種是循環(huán)執(zhí)行多個(gè)SQL語(yǔ)句宣渗,另外一種則是采用JDBC提供的Batch功能抖所,具體如下所示

 @Test
    public void testBatch() throws ClassNotFoundException, SQLException {

        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        String sql = "insert into user(id, name) values(?, 'Tom')";
        PreparedStatement statement = connection.prepareStatement(sql);
        long start = System.currentTimeMillis();
        // 普通循環(huán)執(zhí)行
        for (int i = 0; i < 1000; i++){
            statement.setObject(1, i);
            statement.executeUpdate();
        }

        long end = System.currentTimeMillis();

        System.out.printf("cost time %d\n", end - start);

        statement.close();

        statement = connection.prepareStatement(sql);

        start = System.currentTimeMillis();
        // 使用Batch執(zhí)行
        for (int i = 1001 ; i < 2000; i++){
            statement.setObject(1, i);
            statement.addBatch();
        }
        statement.executeBatch();
        end = System.currentTimeMillis();

        System.out.printf("cost time %d\n", end - start);

        statement.close();
        connection.close();
    }

有點(diǎn)可惜的是,經(jīng)過(guò)測(cè)試痕囱,這兩種方式的性能很接近田轧,不知道是我操作的問(wèn)題還是事實(shí)確實(shí)是如此,還望有懂這個(gè)的朋友指點(diǎn)指點(diǎn)鞍恢,

元數(shù)據(jù)

所謂的元數(shù)據(jù)傻粘,也就是是用于定義其他數(shù)據(jù)的數(shù)據(jù),在SQL中有序,元數(shù)據(jù)可以理解為就是數(shù)據(jù)庫(kù)抹腿、表的定義數(shù)據(jù),在JDBC中旭寿,有三種類型的元數(shù)據(jù)警绩,分別是DatabaseMetaDataResultSetMetaData盅称,ParameterMetaData肩祥,分別是數(shù)據(jù)庫(kù)相關(guān)信息,結(jié)果集相關(guān)信息缩膝,以及PreparedStatement語(yǔ)句中的相關(guān)參數(shù)信息混狠,具體操作如下所示


    @Test
    public void testMetaData() throws ClassNotFoundException, SQLException {

        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER_NAME, SQL_PASSWORD);

        // DatabaseMetaData 相關(guān)的信息,比如數(shù)據(jù)庫(kù)供應(yīng)商名稱疾层,版本等
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        System.out.println("version : " + databaseMetaData.getDatabaseMajorVersion());
        System.out.println("name : " + databaseMetaData.getDatabaseProductName());

        int id = 4;
        String sql = "select id, name from user where id < ? ";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setObject(1, id);
        
        // ParameterMetaData 相關(guān)信息将饺,比如參數(shù)個(gè)數(shù)
        ParameterMetaData parameterMetaData = statement.getParameterMetaData();
        int paramCount = parameterMetaData.getParameterCount();
        System.out.println("parameter count : " + paramCount);

        ResultSet resultSet = statement.executeQuery();
      
        // ResultSetMetaData 相關(guān)信息,比如取出來(lái)的數(shù)據(jù)的列名
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        int resultCount = resultSetMetaData.getColumnCount();
        System.out.println("resultCount : " + resultCount);
        for (int i = 0; i < resultCount; i++) {
            System.out.print(resultSetMetaData.getColumnName(i + 1) + "  ");
        }
        System.out.println();
    }

事務(wù)管理

所謂的事務(wù)痛黎,是指做一件事情予弧,這件事情有多個(gè)步驟,這多個(gè)步驟這件湖饱,要么都完成掖蛤,要么都不完成,事務(wù)具有四個(gè)特性ACID井厌,分別是原子性蚓庭,一致性,獨(dú)立性仅仆,持久性
在JDBC中器赞,可以通過(guò)connection.setAutoCommit(true/false);開(kāi)控制事務(wù),默認(rèn)為true墓拜,也就是默認(rèn)自動(dòng)提交事務(wù)拳魁。通過(guò)connection.commit()手動(dòng)提交事務(wù),connection.setSavepoint();設(shè)置保存點(diǎn)撮弧,connection.rollback();回滾到保存到潘懊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末姚糊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子授舟,更是在濱河造成了極大的恐慌救恨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件释树,死亡現(xiàn)場(chǎng)離奇詭異肠槽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)奢啥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門秸仙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人桩盲,你說(shuō)我怎么就攤上這事寂纪。” “怎么了赌结?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵捞蛋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我柬姚,道長(zhǎng)拟杉,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任量承,我火速辦了婚禮搬设,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撕捍。我一直安慰自己拿穴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布卦洽。 她就那樣靜靜地躺著,像睡著了一般斜棚。 火紅的嫁衣襯著肌膚如雪阀蒂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天弟蚀,我揣著相機(jī)與錄音蚤霞,去河邊找鬼。 笑死义钉,一個(gè)胖子當(dāng)著我的面吹牛昧绣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捶闸,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼夜畴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拖刃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起贪绘,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤兑牡,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后税灌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體均函,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年菱涤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苞也。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粘秆,死狀恐怖如迟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情翻擒,我是刑警寧澤氓涣,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站陋气,受9級(jí)特大地震影響劳吠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巩趁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一痒玩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧议慰,春花似錦蠢古、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至炉菲,卻和暖如春堕战,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拍霜。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工嘱丢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人祠饺。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓越驻,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缀旁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • JDBC概述 在Java中记劈,數(shù)據(jù)庫(kù)存取技術(shù)可分為如下幾類:JDBC直接訪問(wèn)數(shù)據(jù)庫(kù)、JDO技術(shù)诵棵、第三方O/R工具抠蚣,如...
    usopp閱讀 3,543評(píng)論 3 75
  • 本節(jié)介紹Statement接口及其子類PreparedStatement和CallableStatement。 它...
    zlb閱讀 1,165評(píng)論 0 0
  • 1 引言# 本文主要講解JDBC怎么演變到Mybatis的漸變過(guò)程履澳,重點(diǎn)講解了為什么要將JDBC封裝成Mybait...
    七寸知架構(gòu)閱讀 76,497評(píng)論 36 980
  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis 嘶窄? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥(niǎo)慢飛閱讀 5,527評(píng)論 0 4
  • 你用月光杯 干盡了一江春水 而我想用一首詩(shī) 起舞你波濤洶涌的江湖 不必介懷 是什么弄傷了你的心 以文字做針線吧 縫...
    花千魂閱讀 227評(píng)論 0 0