(四)04-使用JDBC重寫博客項目

bug修復(fù)

前面我們的項目中,Blog類和User類的id屬性設(shè)置為long類型豹障,實際上應(yīng)該設(shè)置為Long類型會更好描睦。因為:

  1. Java中Long 類型建立的時候如果沒賦值,會默認(rèn)給一個null.而long類型建立的時候如果沒有賦值判哥,則是0L。而id屬性是數(shù)據(jù)庫自動去填充值的碉考,不應(yīng)該有默認(rèn)值塌计,我們可以通過是否為null來判斷是否存在記錄。
  2. Long提供了很多API雨效, 比如查詢蛤高、賦空值等簡便撵彻, 可以利用Long本身的優(yōu)化;如你使用Long.valueOf時 可以利用緩存的-128至127之間的值热芹; 還有從使用hibernate、el表達(dá)式等都是包裝類型嫩痰,減少了裝箱/拆箱剿吻;

我們還得修改模型類的getId、setId的返回類型串纺。

同理丽旅,模型類比如購物車Cart,它的字段頁應(yīng)該是Integer而不是int纺棺。相應(yīng)的我們要修改那些傳入?yún)?shù)long參數(shù)對應(yīng)的修改為Long才行榄笙。一般模型類中的方法參數(shù)最好都是封裝類型而不是基本類型。

model類里面去掉id = count++;

因為id自增交由數(shù)據(jù)庫去完成祷蝌,所以我們不必使用java代碼去實現(xiàn)茅撞。所以我們要去修改User模型類和Blog模型類。

User模型類需要添加新的字段description

相應(yīng)的修改用戶倉庫初始化代碼和用戶模型類構(gòu)造器

數(shù)據(jù)庫通用操作封裝到DBHleper工具類

package com.jspblog.utils;

import com.jspblog.model.Blog;
import com.jspblog.model.Project;
import com.jspblog.model.User;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class DBHelper {

    public static String driver = "com.mysql.jdbc.Driver";
    public static String connectionString = "jdbc:mysql://127.0.0.1:3306/jspblog?useSSL=false";
    public static String username = "root";
    public static String password = "123456";

    // 1巨朦、加載MYSQL驅(qū)動米丘,這里MySQL的JDBC驅(qū)動類是com.mysql.jdbc.Driver,要求類路徑中包含相應(yīng)的Driver類
    static {
        try {
            Class.forName(driver).newInstance();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 2糊啡、連接到MYSQL拄查,通過DriverManger來創(chuàng)建Connection對象,獲取數(shù)據(jù)庫連接
    public static Connection getConnection() throws Exception {
        return DriverManager.getConnection(connectionString, username, password);
    }

    // 3棚蓄、創(chuàng)建PreparedStatement用以執(zhí)行SQL語句

    // 插入操作堕扶,我們希望獲得插入記錄后的編號,也就是返回值是id
    public static Long create(String sql) {

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

        try {
            //2,連接到MYSQL
            connection = getConnection();
            //3梭依,PreparedStatement用以執(zhí)行SQL語句
            statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            statement.executeUpdate();
            //4稍算,ResultSet用于接收SQL語句執(zhí)行后的結(jié)果,更新之后我們只需要獲取更新記錄的id屬性即可役拴,而不是整個記錄對象
            resultSet = statement.getGeneratedKeys();
            //5糊探、遍歷并解析結(jié)果
            if (resultSet.next()) {
                return resultSet.getLong(1);
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            //6,清理數(shù)據(jù)庫連接相關(guān)的所有資源
            clear(resultSet, statement, connection);
        }
    }

    // 刪除操作,用于remove動作
    // 由于刪除之后就不存在就該記錄了侧到,所以不需要遍歷結(jié)果頁不用返回id勃教,直接返回數(shù)字0表示刪除成功
    public static int delete(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;

        try {
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            return statement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            clear(null, statement, connection);
        }
    }

    //查詢單條記錄,查詢就應(yīng)該返回對象匠抗,而不像插入那樣只要返回id故源。由于查詢的可能是不同對象,所以使用泛型
    public static Blog queryBlog(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            if (resultSet.first()) {
                int userId = resultSet.getInt("author");
                User user = queryUser("select * from user where id="+userId);
                Blog blog = new Blog(resultSet.getString("title"),resultSet.getString("content"),resultSet.getDate("createdTime"),user);
                return blog;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            clear(null, statement, connection);
        }
    }

    //查詢單條記錄汞贸,查詢就應(yīng)該返回對象绳军,而不像插入那樣只要返回id。由于查詢的可能是不同對象矢腻,所以使用泛型
    public static User queryUser(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            if (resultSet.first()) {
                User user = new User(resultSet.getString("email"),resultSet.getString("username"),resultSet.getString("password"));
                return user;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            clear(null, statement, connection);
        }
    }

    //查詢單條記錄门驾,查詢就應(yīng)該返回對象,而不像插入那樣只要返回id多柑。由于查詢的可能是不同對象奶是,所以使用泛型
    public static Project queryProject(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            if (resultSet.first()) {
                Project project = new Project(resultSet.getString("name"),resultSet.getString("description"),resultSet.getString("url"),resultSet.getString("logo"));
                return project;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            clear(null, statement, connection);
        }
    }

    //查詢多條記錄,與查詢單條記錄不同在于是遍歷結(jié)果集放入數(shù)組中。由于查詢的可能是不同對象竣灌,所以使用泛型
    @SuppressWarnings("unchecked")
    public static List<Blog> queryBlogList(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            List<Blog> list = new ArrayList<Blog>();
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();

            while(resultSet.next()) {
                int userId = resultSet.getInt("author");
                User user = queryUser("select * from user where id="+userId);
                Blog blog = new Blog(resultSet.getString("title"),resultSet.getString("content"),resultSet.getDate("createdTime"),user);
                list.add(blog);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            clear(null, statement, connection);
        }
    }

    //查詢多條記錄,與查詢單條記錄不同在于是遍歷結(jié)果集放入數(shù)組中聂沙。由于查詢的可能是不同對象,所以使用泛型
    @SuppressWarnings("unchecked")
    public static List<Project> queryProjectList(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            List<Project> list = new ArrayList<Project>();
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();

            while(resultSet.next()) {
                Project project = new Project(resultSet.getString("name"),resultSet.getString("description"),resultSet.getString("url"),resultSet.getString("logo"));
                list.add(project);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            clear(null, statement, connection);
        }
    }

    //查詢多條記錄,與查詢單條記錄不同在于是遍歷結(jié)果集放入數(shù)組中初嘹。由于查詢的可能是不同對象及汉,所以使用泛型
    @SuppressWarnings("unchecked")
    public static List<User> queryUserList(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            List<User> list = new ArrayList<User>();
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();

            while(resultSet.next()) {
                User user = new User(resultSet.getString("email"),resultSet.getString("username"),resultSet.getString("password"),resultSet.getString("description"));
                list.add(user);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            clear(null, statement, connection);
        }
    }

    // 計數(shù)
    //技術(shù)我們一般傳入sql語句是select count(*)這樣的語句,返回結(jié)果只有一條記錄屯烦,頁只有一個字段坷随。該字段存的就是count的記錄數(shù)目
    public static int queryCount(String sql) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = DBHelper.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            //由于結(jié)果肯定只有一條記錄,所以我們?nèi)〕鰂irst結(jié)果即可
            if (resultSet.first()) {
                return resultSet.getInt(1);  //獲取結(jié)果集中第一列的值驻龟,count語句返回的本來就只有一個字段
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            clear(null, statement, connection);
        }
    }

    //6温眉、清理數(shù)據(jù)庫連接相關(guān)的所有資源
    private static void clear(ResultSet resultSet, Statement statement, Connection connection) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }

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

            if (connection != null) {
                connection.close();
            }
        } catch (SQLException ignored) {

        }
    }
}

Statement.RETURN_GENERATED_KEYS用于獲取自動生成的鍵值,這里是自增的id號翁狐。這里也就是我們不必給數(shù)據(jù)庫對象的id屬性賦值芍殖,在執(zhí)行sql語句的時候,添加該代碼會自動往記錄的id自動填入一個自動增長的數(shù)字谴蔑。
getGeneratedKeys();用于獲取主鍵,也就是上面我們執(zhí)行插入語句時龟梦,自動填充的id字段的值隐锭。

新建數(shù)據(jù)庫表project

執(zhí)行語句如下:

CREATE TABLE `project` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `description` longtext NOT NULL,
  `url` varchar(255) NOT NULL,
  `logo` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

保持原Servlet不變,修改模型類

比如我們ProjectRepository類中的getAll方法:

public List<Project> getAll() {
    return projects;
}

應(yīng)該修改為:

public List<Project> getAll() {
        return DBHelper.queryProjectList("select * from project");
}

因為Servlet獲取數(shù)據(jù)是去調(diào)用模型類中的方法而已计贰,而獲取數(shù)據(jù)修改為從數(shù)據(jù)庫中讀取也是把模型類中獲取的數(shù)據(jù)的方法體修改為調(diào)用DBHelper執(zhí)行sql語句而已钦睡。在Servlet中調(diào)用的模型類方法不變,變更的是模型類方法的實現(xiàn)躁倒,所以自然不需要修改Servlet文件荞怒。

而且private static List<Project> projects = new ArrayList<>();屬性也可以去掉了洒琢。因為之前沒有數(shù)據(jù)庫,所以使用一個數(shù)組屬性來保存多個對象褐桌,比如我們要獲取所有項目信息就去訪問這個數(shù)組屬性∷ヒ郑現(xiàn)在有了數(shù)據(jù)庫之后,要獲取所有項目信息只要調(diào)用getAll()方法荧嵌,得到的返回值就是一個包含所有項目信息的數(shù)組呛踊,我們直接使用方法的返回值就行,就不需要該數(shù)組屬性了啦撮。

其他方法比如User谭网、Blog等相關(guān)的多個類也做這樣的修改,模型類中獲取數(shù)據(jù)都改成使用DBHelper類從數(shù)據(jù)庫獲取數(shù)據(jù)赃春,去掉數(shù)組屬性愉择。

修改jsp文件里面引入類的包名,由mvc改為jspblog

把模型類中的數(shù)據(jù)初始化代碼刪除掉织中,通過Navicate在數(shù)據(jù)庫中錄入數(shù)據(jù)

把在WEB-INF/lib目錄里面放入數(shù)據(jù)庫驅(qū)動的jar包mysql-connector-java-5.1.40-bin.jar

必須完成上面全部的修改后锥涕,項目才能運行。

使用JDBC先完成創(chuàng)建博客抠璃、博客列表站楚、博客詳情三個功能與數(shù)據(jù)庫交互

到此,就完成了博客項目使用JDBC與數(shù)據(jù)庫交互的全部改寫搏嗡,測試通過窿春。

提交到git倉庫

創(chuàng)建.gitignore文件,由于我們之前使用oschina自動創(chuàng)建的.gitignore文件采盒,所以修改該文件后還是無法生效旧乞,應(yīng)該執(zhí)行下面操作清除一下緩存cache,才能使修改后的.gitignore 生效磅氨。

git rm -r --cached .  #清除緩存  
git add . #重新trace file  
git commit -m "update .gitignore尺栖,(四)04-使用JDBC重寫博客項目" #提交和注釋  
 git push git@git.oschina.net:michael-first/jdbcblog.git master --force

為了以后提交方便,我們添加如下代碼烦租,以后提交的時候就使用jdbcblog替換代碼倉庫的地址延赌,很方便

git remote add jdbcblog git@git.oschina.net:michael-first/jdbcblog.git
git push jdbcblog master

倉庫: https://git.oschina.net/michael-first/jdbcblog

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市叉橱,隨后出現(xiàn)的幾起案子挫以,更是在濱河造成了極大的恐慌,老刑警劉巖窃祝,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掐松,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機大磺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門抡句,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人杠愧,你說我怎么就攤上這事待榔。” “怎么了殴蹄?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵究抓,是天一觀的道長。 經(jīng)常有香客問我袭灯,道長刺下,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任稽荧,我火速辦了婚禮橘茉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘姨丈。我一直安慰自己畅卓,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布蟋恬。 她就那樣靜靜地躺著翁潘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪歼争。 梳的紋絲不亂的頭發(fā)上拜马,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音沐绒,去河邊找鬼俩莽。 笑死,一個胖子當(dāng)著我的面吹牛乔遮,可吹牛的內(nèi)容都是我干的扮超。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼蹋肮,長吁一口氣:“原來是場噩夢啊……” “哼出刷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坯辩,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤馁龟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后濒翻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年有送,在試婚紗的時候發(fā)現(xiàn)自己被綠了淌喻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡雀摘,死狀恐怖裸删,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阵赠,我是刑警寧澤涯塔,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站清蚀,受9級特大地震影響匕荸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枷邪,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一榛搔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧东揣,春花似錦践惑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至芥吟,卻和暖如春侦铜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背运沦。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工泵额, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人携添。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓嫁盲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親烈掠。 傳聞我的和親對象是個殘疾皇子羞秤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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