Java操作數(shù)據(jù)庫--JDBC

簡介

剛開始介紹了mysql基本語句普碎,但是你會覺得好像不會知道怎么用,它的用途在什么地方纸兔,所以為了提高興趣今天我們來介紹一下JDBC,以后會和MySQL一起更新梅桩。

JDBC,到底jdbc是什么東西呢拜隧?

JDBC(Java Data Base Connectivity,java數(shù)據(jù)庫連接)宿百,是由一些接口和類構(gòu)成的API。是J2SE的一部分洪添,由java.sql,javax.sql包組成垦页。

概述

JDBC是JAVA與數(shù)據(jù)的連接。因為ODBC是完全用C語言編寫的干奢,而JAVA中實現(xiàn)與C語言程序的通信是比較困難的痊焊,因此就產(chǎn)生了由JAVA語言編寫的用于JAVA程序與數(shù)據(jù)庫連接的接口技術(shù)。JDBC與具體的某種數(shù)據(jù)庫連接忿峻,是通過由數(shù)據(jù)庫廠商提供的驅(qū)動來作為中間橋梁實現(xiàn)的薄啥。在JDBC API類庫一般在java.sql包中,它包含了用于實現(xiàn)與數(shù)據(jù)庫連接的其它功能的類炭菌,包括與數(shù)據(jù)庫建立連接罪佳、傳送查詢和接受查詢結(jié)果。

建立數(shù)據(jù)庫

為了演示JDBC我們先來創(chuàng)建一個數(shù)據(jù)庫黑低,為下面的做鋪墊赘艳,之前裝的數(shù)據(jù)庫客戶端是英文版的,今天我們使用的是版本較低的中文yog客戶端克握,這樣看起來比較方便蕾管。

下載驅(qū)動

既然java和數(shù)據(jù)庫建立連接的橋梁是驅(qū)動,那當(dāng)然首先我們得有驅(qū)動菩暗,我們今天說的的mysql掰曾,所以先去mysql官網(wǎng)下載驅(qū)動然后解壓,你不想去下載的話今天的文件可以關(guān)注公眾號 代碼黑洞 后臺獲取一下停团,里面這些都有了旷坦。官網(wǎng)下載地址:https://dev.mysql.com/downloads/connector/j/

下載好之后我們要去把這個jar包添加到我們創(chuàng)建的項目的Build Path中,如下圖佑稠。


JDBC實例

實現(xiàn)jdbc有這么五個步驟:

1.注冊驅(qū)動

2.創(chuàng)建連接

3.創(chuàng)建語句

4.執(zhí)行語句

5.處理結(jié)果

6.關(guān)閉資源

我們一個一個來看秒梅。

1.注冊驅(qū)動

注冊驅(qū)動 有三種方式:

????方式一:

/*DriverManager中的registerDriver(new Drivers());參數(shù)傳的就是一個Drivers

?* 可以注冊很多驅(qū)動,比如SQL sever舌胶,MySQL捆蜀,Oracle等

?* 通過查看源碼我們可以只知道這個Drivers的存儲方式其實是一個vector

?* 在程序運(yùn)行時給定了url就會在這個vector里進(jìn)行比對看能不能建立連接

?* 如果可以就返回結(jié)果,如果把vector遍歷完了都不能建立連接那就會報錯

?*

?* 使用這種方式去注冊驅(qū)動會造成DriverManager中產(chǎn)生兩個一樣的

?* 驅(qū)動,并會對具體的驅(qū)動類產(chǎn)生依賴辆它。不利于移植誊薄,和擴(kuò)展。

?*/

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

方式一:

/*

?* 使用鍵值對的方式registerDriver里邊有一個loadInitialDrivers方法?* 會去找通過鍵值對注冊的驅(qū)動信息锰茉,但是分割方式是以:而不是=的方式

?* 所以用這個鍵值對的方式去注冊很多個驅(qū)動的時候中間使用:分割的

?* 如:System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver:com.oracle.jdbc.Driver");

?* 就注冊了mysql和oracle的兩個驅(qū)動

?* 雖然不會對具體的驅(qū)動類產(chǎn)生依賴呢蔫;但注冊不太方便,所以很少使用飒筑。?

*/

System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");

方式三:

/*

?* 通過這種Class.forName的方式去找這個文件并裝載到虛擬機(jī)中來

?* 即Java反射機(jī)制咐刨,會根據(jù)這個名稱去找編譯好的.class文件

* com.mysql.jdbc這是包名,這個跟導(dǎo)不導(dǎo)包是沒有關(guān)系的

* 因為它只是一個字符串扬霜,這個根據(jù)這個classPath只是找到了包,

* 包這是個文件夾而并不會接著往包里邊去找所以要寫上包名

* 告訴虛擬機(jī)去這個路徑下找然后裝載到j(luò)vm虛擬機(jī)里來

* 所以異常就是ClassNotFoundException而涉,class文件沒有找到異常

* 推薦這種方式著瓶,不會對具體的驅(qū)動類產(chǎn)生依賴。

* 根據(jù)Java反射的特性就可以知道用反射是極大的提高了擴(kuò)展性的

*/

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

2.建立連接

/*

*? 2.建立連接

* Connection conn = DriverManager.getConnection(url, user, password);

* 參數(shù)是:url啼县,user材原,password

* 為什么是url呢因為一半請求的都是網(wǎng)絡(luò)主機(jī)

* 所以要指定網(wǎng)絡(luò)主機(jī)數(shù)據(jù)庫的url然后帶著用戶名和密碼去

* 建立連接,告訴服務(wù)器你要連接哪個用戶的數(shù)據(jù)庫

* 如果沒有密碼那就是password為空字符

*?

* url格式:(這不需要去記百度都能找到)

* JDBC:子協(xié)議:子名稱//主機(jī)名:端口/數(shù)據(jù)庫名季眷?屬性名=屬性值&…

* User,password可以用“屬性名=屬性值”方式告訴數(shù)據(jù)庫余蟹;

* 其他參數(shù)如:useUnicode=true&characterEncoding=GBK

* 這個其他參數(shù)就是指定解碼格式,用來解析返回來的數(shù)據(jù)

* 如果返回回來的是utf-8編碼方式的數(shù)據(jù)子刮,你用GBK的方式去

* 解析反饋回來的數(shù)據(jù)威酒,那就會出現(xiàn)亂碼的情況

* 所以如果節(jié)碼方式不指定,虛擬機(jī)程序時會給出警告

*/

String url = "jdbc:mysql://localhost:3306/jdbc";

String user = "root";

String password = "123456";

Connection conn = DriverManager.getConnection(url, user, password);

3.創(chuàng)建語句

Statement 對象

一旦我們獲得了數(shù)據(jù)庫的連接挺峡,我們就可以和數(shù)據(jù)庫進(jìn)行交互葵孤。JDBC 的 ?Statement,CallableStatement 和 PreparedStatement 接口定義的方法和屬性橱赠,可以讓你發(fā)送 SQL 命令或 PL/SQL 命令到數(shù)據(jù)庫尤仍,并從你的數(shù)據(jù)庫接收數(shù)據(jù)。

在數(shù)據(jù)庫中狭姨,它們還定義了幫助 Java 和 SQL 數(shù)據(jù)類型之間轉(zhuǎn)換數(shù)據(jù)差異的方法宰啦。

下表提供了每個接口的用途概要,根據(jù)實際目的決定使用哪個接口饼拍。

接口推薦使用

Statement可以正常訪問數(shù)據(jù)庫赡模,適用于運(yùn)行靜態(tài) SQL 語句。 Statement 接口不接受參數(shù)惕耕。

PreparedStatement計劃多次使用 SQL 語句纺裁, PreparedStatement 接口運(yùn)行時接受輸入的參數(shù)。

CallableStatement適用于當(dāng)你要訪問數(shù)據(jù)庫存儲過程的時候, CallableStatement 接口運(yùn)行時也接受輸入的參數(shù)欺缘。

我們先演示的是Statement

Statement st = conn.createStatement();

4.執(zhí)行數(shù)據(jù)庫語句

當(dāng)你創(chuàng)建了一個 Statement 對象之后栋豫,你可以用它的三個執(zhí)行方法的任一方法來執(zhí)行 SQL 語句。

boolean execute(String SQL) :?如果 ResultSet 對象可以被檢索谚殊,則返回的布爾值為 true 丧鸯,否則返回 false 。當(dāng)你需要使用真正的動態(tài) SQL 時嫩絮,可以使用這個方法來執(zhí)行 SQL DDL 語句丛肢。

int executeUpdate(String SQL) :?返回執(zhí)行 SQL 語句影響的行的數(shù)目。使用該方法來執(zhí)行 SQL 語句剿干,是希望得到一些受影響的行的數(shù)目蜂怎,例如,INSERT置尔,UPDATE 或 DELETE 語句杠步。

ResultSet executeQuery(String SQL) :?返回一個 ?ResultSet 對象。當(dāng)你希望得到一個結(jié)果集時使用該方法榜轿,就像你使用一個 SELECT 語句幽歼。

我們就用ResultSet來執(zhí)行數(shù)據(jù)庫語句:

ResultSet rs = st.executeQuery("select * from user");

5.處理結(jié)果

/*

* 5.處理結(jié)果

* 學(xué)過集合框架都知道迭代器的使用,比如:iterator所以這個rs.next()

* 就是去查找下一行數(shù)據(jù)谬盐。按行遍歷的所以我們只需要按字段去拿

* While(rs.next()){

*? rs.getString(“col_name”);//col_name字段(列名)

*? rs.getInt(“col_name”);

*? ....

* }

*/

while (rs.next()) {

//這里時也是去拿字段只不過更加能體現(xiàn)面向?qū)ο蟮乃枷耄?/p>

//每一個字段都是一個對象

//和getString甸私,getInt等,是一樣的

System.out.println(rs.getObject(1) + "\t" + rs.getObject(2) + "\t"+ rs.getObject(3) + "\t" + rs.getObject(4));

}

6.釋放資源

/*

*? 6.釋放資源

*? 釋放ResultSet, Statement,Connection.

*? 數(shù)據(jù)庫連接(Connection)是非常稀有的資源飞傀,用完后必須馬上釋放

*? 如果Connection不能及時正確的關(guān)閉將導(dǎo)致系統(tǒng)宕機(jī)皇型。

*? Connection的使用原則是盡量晚的去建立連接,盡量早的釋放助析。

*? 也就是盡量減少占用數(shù)據(jù)庫的時間犀被,減輕數(shù)據(jù)庫的壓力

*/?

????rs.close();

????st.close();

????conn.close();

改進(jìn)

上述所示例子有很多問題需要處理,不夠嚴(yán)謹(jǐn)外冀。我們就需來對它一步一步的優(yōu)化寡键。

首先為了提高擴(kuò)展性,我們可以把建立連接時Connection參數(shù)定義為private static final


我們發(fā)現(xiàn)finally關(guān)閉資源的時候處理異常太麻煩雪隧,每次都要嵌套些這么多就很煩西轩,所以還是需要優(yōu)化。于是我們打算寫一個名叫JdbcUtils工具類來完成這件事脑沿,同樣的先把參數(shù)定義為全局常量


把構(gòu)造方法私有化藕畔,避免產(chǎn)生對象,我們寫這個工具類是直接使用的不需要創(chuàng)建對象

/*

*注冊驅(qū)動庄拇。將其聲明為static代碼塊即靜態(tài)代碼塊注服,是在類中獨立于類成員的static語句塊當(dāng)JVM加載類時就會執(zhí)行

*它不依賴類特定的實例韭邓,被類的所有實例共享。

*

* 在這里就非常有用了溶弟,使用jdbc第一個步驟就是要先注冊驅(qū)動

* 把注冊驅(qū)動寫成靜態(tài)代碼塊女淑,當(dāng)類加載時就會被執(zhí)行達(dá)到注冊的目的無需單獨寫成在方法再去調(diào)用,那樣麻煩9加鸭你!

*/

/*

*?建立連接,還是一樣擒权,把參數(shù)抽取出來袱巨,定義為全局變量,提高其擴(kuò)展性碳抄,比如當(dāng)你改了

* 數(shù)據(jù)庫密碼的時候愉老,就不用在去修改源代碼。

* 當(dāng)然還有更好的方法是用Properties集合把這些信息保存到配置文件中去剖效,大大提高了擴(kuò)展性

* 當(dāng)信息改動只需要更改配置文件俺夕,而不需要去改源代碼。這里就不再演示Properties贱鄙。

*/

/*

*將關(guān)閉資源單獨分裝到自己寫的工具類中,提高復(fù)用性姨谷,因為關(guān)閉資源需要處理的異常寫起來很麻煩

*而又是必須要處理逗宁,所以單獨封裝,可以節(jié)省時間和空間

*/

當(dāng)我們需要的去連接到數(shù)據(jù)庫的時候梦湘,就可以很方便的進(jìn)行瞎颗,如下所示:

測試改進(jìn)效果

這樣代碼就會簡潔很多。運(yùn)行結(jié)果如下捌议,這就查詢到了數(shù)據(jù)庫里的信息

繼續(xù)優(yōu)化

既然我們這種方式是需要私有化構(gòu)造函數(shù)的哼拔,那我們就想到了,能用單類來完成它

/*

?* 單類模式實現(xiàn)工具類 創(chuàng)建方法一 餓漢式(即時加載模式)

* 特點:

* 1瓣颅、單例類只能有一個實例倦逐。

* 2、單例類必須自己創(chuàng)建自己的唯一實例宫补。

* 3檬姥、單例類必須給所有其他對象提供這一實例。

* 單例模式保證了全局對象的唯一性

*/

/* 思路:

* 單類:通過將構(gòu)造方法限定為private避免了類在外部被實例化粉怕,

* 在同一個虛擬機(jī)范圍內(nèi)健民,JdbcUtilsSingle的唯一實例

* 只能通過getInstance()方法訪問。

*

* 第一步:創(chuàng)建自己的唯一實例

* 第二部:對外提供getInstance()方法獲取實例

*/

然后其他地方就和第一次改進(jìn)后一樣

注冊驅(qū)動

后面的一樣那就不在贅述贫贝。

測試單類工具類

懶漢式單類設(shè)計模式

單類實現(xiàn)二:有時候把對象構(gòu)造出來但是不一定會用的時候用這種延時加載(也叫惰性加載)的方式秉犹,我們什么時候需要再去實例化對象

創(chuàng)建getInstance()方法去讓其他類拿到這個對象

/*

* 但是對于以上的getInstance()方法來說蛉谜,還是有些問題到,如果此時有兩個線程崇堵,線程A執(zhí)行到1處型诚,讀取了instance為null,

* 然后cpu就被線程B搶去了筑辨,此時俺驶,線程A還沒有對instance進(jìn)行實例化。

* 因此棍辕,線程B讀取instance時仍然為null暮现,于是,它對instance進(jìn)行實例化了楚昭。

* 然后栖袋,cpu就被線程A搶去了。此時抚太,線程A由于已經(jīng)讀取了instance的值并且認(rèn)為它為null

* 所以塘幅,再次對instance進(jìn)行實例化。所以尿贫,線程A和線程B返回的不是同一個實例电媳。

* 這就出現(xiàn)了線程安全問題

*/

/*

* 那么線程安全問題怎么解決呢?

* 方法一:在方法前面加synchronized修飾庆亡。這樣肯定不會再有線程安全問題匾乓。?

* 但是,這種解決方式又谋,假如有100個線程同時執(zhí)行拼缝,那么,每次去

* 執(zhí)行g(shù)etInstance方法時都要先獲得鎖再去執(zhí)行方法體彰亥,如果沒有鎖咧七,

* 就要等待,耗時長任斋,效率就很低继阻。因此,還是需要改進(jìn)

*/

/* 解決方法改進(jìn):

* 加同步代碼塊废酷,減少鎖的顆粒大小穴翩,即能用局部鎖就不用函數(shù)鎖。我們發(fā)現(xiàn)锦积,只有第一次instance為null的

* 時候芒帕,才去創(chuàng)建實例,而判斷instance是否為null是讀的操作丰介,不可能存在線程安全

* 問題背蟆,所以鉴分,我們只需要對創(chuàng)建實例的代碼進(jìn)行同步代碼塊的處理,也就是所謂的對可

* 能出現(xiàn)線程安全的代碼進(jìn)行同步代碼塊的處理带膀。

*/

/*但是我們這樣處理就沒有問題了嗎志珍?

* 同理我們先來做個分析,假設(shè)有兩個線程垛叨,線程A和線程B伦糯,

* 首先線程A讀取instance值為null嗽元,然后cpu就被線程B搶了去獲得執(zhí)行權(quán)敛纲,

* 線程B再來判斷instance值為null,接著線程B依然持有執(zhí)行權(quán)往下執(zhí)行了同

* 步代碼塊中的代碼剂癌,對instance進(jìn)行實例化淤翔。

* 然后,線程A獲得cpu的執(zhí)行權(quán)佩谷,由于線程A之前已經(jīng)判斷instance值為null旁壮,

* 于是線程A直接就執(zhí)行了它后面的同步代碼塊代碼,對instance進(jìn)行實例化谐檀。

*這樣就實例化了兩個對象抡谐,實則只用的到一個對象,造成資源浪費桐猬。

*

*所以從上面的分析來看童叠,我們需要繼續(xù)改進(jìn)

*那就是加雙重if判斷

*/

/*但是。课幕。。哈哈盡管這樣還是不能保證代碼百分百一定沒有線程安全問題了

* 因為五垮,這里會涉及到一個指令重排序問題乍惊,雖然幾率很小,但是還是有存在的可能

* 所以再來一步把之前那句private static JdbcUtilsSingle1 instance = null;

* 加上volatile關(guān)鍵字放仗,因為volatile可以禁止指令重排序润绎。如下:

* private static volatile JdbcUtilsSingle1 instance = null;

*/

現(xiàn)在可以保證是完全沒有問題了,后面的結(jié)果處理诞挨,關(guān)閉資源和之前是一樣的那就不在贅述莉撇,如何使用,也是和單類設(shè)計模式一的測試一樣的也就不再說了惶傻。

那么通過上述示例棍郎,我們就把,jdbc银室,多線程中線程安全問題以及單類的兩種設(shè)計模式(懶漢式涂佃,餓漢式)融合貫通起來励翼,不禁讓我感嘆代碼之美。

如果有什么問題可以到公眾號咨詢辜荠,一般是機(jī)器人回復(fù)汽抚,但我看到后會和你一起討論。

如果這中有什么問題歡迎在評論區(qū)留言指正伯病,共同進(jìn)步造烁。



????????????????????????????????????????????????????????????????歡迎關(guān)注公眾號 代碼黑洞

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市午笛,隨后出現(xiàn)的幾起案子惭蟋,更是在濱河造成了極大的恐慌,老刑警劉巖季研,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敞葛,死亡現(xiàn)場離奇詭異,居然都是意外死亡与涡,警方通過查閱死者的電腦和手機(jī)惹谐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驼卖,“玉大人氨肌,你說我怎么就攤上這事∽眯螅” “怎么了怎囚?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長桥胞。 經(jīng)常有香客問我恳守,道長,這世上最難降的妖魔是什么贩虾? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任催烘,我火速辦了婚禮,結(jié)果婚禮上缎罢,老公的妹妹穿的比我還像新娘伊群。我一直安慰自己,他們只是感情好策精,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布舰始。 她就那樣靜靜地躺著,像睡著了一般咽袜。 火紅的嫁衣襯著肌膚如雪丸卷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天询刹,我揣著相機(jī)與錄音及老,去河邊找鬼抽莱。 笑死,一個胖子當(dāng)著我的面吹牛骄恶,可吹牛的內(nèi)容都是我干的食铐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼僧鲁,長吁一口氣:“原來是場噩夢啊……” “哼虐呻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寞秃,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤斟叼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后春寿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朗涩,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年绑改,在試婚紗的時候發(fā)現(xiàn)自己被綠了谢床。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡厘线,死狀恐怖识腿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情造壮,我是刑警寧澤渡讼,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站耳璧,受9級特大地震影響成箫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旨枯,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一蹬昌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧召廷,春花似錦、人聲如沸账胧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽治泥。三九已至筹煮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間居夹,已是汗流浹背败潦。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工本冲, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人劫扒。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓檬洞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沟饥。 傳聞我的和親對象是個殘疾皇子添怔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法贤旷,內(nèi)部類的語法广料,繼承相關(guān)的語法,異常的語法幼驶,線程的語...
    子非魚_t_閱讀 31,664評論 18 399
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,814評論 0 11
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理艾杏,服務(wù)發(fā)現(xiàn),斷路器盅藻,智...
    卡卡羅2017閱讀 134,704評論 18 139
  • 前些天购桑,Jenny發(fā)了一條朋友圈,附上兩張照片萧求,第一張是一個男生的背影其兴,他牽著她的手;第二張夸政,是兩張紅本本元旬。配文是...
    TF_Java閱讀 173評論 0 1
  • 很多人早上起來只用清水洗臉匀归,晚上睡覺面部是會排毒的,會分泌出來很多油脂和死皮垃圾耗帕,此時如果你沒有清潔到位的話穆端,時間...
    唯有妳懂我閱讀 190評論 0 0