JDBC颜曾、IO流

Junit是一個基于Java語言的單元測試框架。是白盒測試的一種技術秉剑。

①測試方法上必須使用@Test進行修飾

? ? ? ②測試方法必須使用public void 進行修飾泛豪,不能帶任何的參數(shù)

? ? ? ③新建一個源代碼目錄來存放我們的測試代碼,即將測試代碼和項目業(yè)務代碼分開

? ? ? ④測試類所在的包名應該和被測試類所在的包名保持一致

? ? ? ⑤測試單元中的每個方法必須可以獨立測試侦鹏,測試方法間不能有任何的依賴

? ? ? ⑥測試類使用Test作為類名的后綴(不是必須)

? ? ? ⑦測試方法使用test作為方法名的前綴(不是必須)

JDBC(Java DataBase Connectivity,java數(shù)據(jù)庫連接)是一種用于執(zhí)行SQL語句的Java API诡曙,可以為多種 關系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成种柑。JDBC提供了一種基準岗仑,據(jù)此可以 構建更高級的工具和接口,使數(shù)據(jù)庫開發(fā)人員能夠編寫數(shù)據(jù)庫應用程序聚请。

JDBC可以在各種平臺上使用Java荠雕,如Windows,Mac OS和各種版本的UNIX驶赏。

構建JDBC應用程序涉及以下六個步驟:

導入JDBC驅動包:需要下載包含數(shù)據(jù)庫編程所需的JDBC的jar包炸卑。

?注冊JDBC驅動程序:要求您初始化驅動程序,以便您可以打開與數(shù)據(jù)庫的通信通道煤傍。

?創(chuàng)建連接:需要使用 D riv e r M a n a g e r.g e t C o n n e c tio n () 方法創(chuàng)建一個Connection對象盖文,該對象表示 與數(shù)據(jù)庫的物理連接。

?執(zhí)行查詢:需要使用類型為Statement的對象來構建和提交SQL語句到數(shù)據(jù)庫蚯姆。?

從結果集中提取數(shù)據(jù):需要使用相應的 R e s ult S e t .g e t X X X () 方法從結果集中檢索數(shù)據(jù)五续。?

釋放資源:需要明確地關閉所有數(shù)據(jù)庫資源,而不依賴于JVM的垃圾收集龄恋。

public class JdbcDemo2 {?

?public static void main(String[] args) {?

?Connection connection=null;

?Statement stat=null;

?ResultSet rs=null; //2注冊驅動?

?try {? ?

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

? ? ? //3獲取連接? ? ? ? ? ??

connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");? ? ? ? ??

? //4創(chuàng)建命令(語句)對象? ? ? ? ? ?

?stat=connection.createStatement();? ? ? ??

? ? //執(zhí)行命令查詢? ? ??

? ? ? rs=stat.executeQuery("select ename,empno from emp");? ? ??

? ? ? //5處理結果? ? ? ? ? ?

?while(rs.next()){ //? ? ?

?? ? ? ? int empno=rs.getInt(1); //? ? ? ? ? ?

?? String empname=rs.getString(2);? ? ? ? ? ?

?? ? int empno=rs.getInt("empno");? ? ? ??

? ? ? ? String empname=rs.getString("ename");? ? ? ? ?

?? ? ? System.out.println(empno+"...."+empname);? ? ? ? ? ? }

PreparedStatement

該P r e p a r e d S t a t e m e n t 的 接口擴展了Statement接口疙驾,它為您提供了一個通用的Statement對象有兩個優(yōu) 點附加功能。

作用:1預編譯郭毕,效率高? 2 安全它碎,避免SQL注入

Connection con = null;

? ? ? ? Statement stmt = null;

? ? ? ? ResultSet resultSet = null;

? ? ? ? try {

? ? ? ? ? ? con = JDBCUtils.getConnection();

? ? ? ? ? ? //? 占位符

? ? ? ? ? ? //預制型的sql語句 好處: 防止sql注入, 語法清晰

? ? ? ? ? ? PreparedStatement ps = con.prepareStatement("select * from users where user_name=?");

? ? ? ? ? ? ps.setString(1,userName);

? ? ? ? ? ? resultSet = ps.executeQuery(); //執(zhí)行

? ? ? ? ? ? while (resultSet.next()) {

? ? ? ? ? ? ? ? int id = resultSet.getInt("id");

? ? ? ? ? ? ? ? String name = resultSet.getString("user_name");

? ? ? ? ? ? ? ? String passsword = resultSet.getString("password");

? ? ? ? ? ? ? ? System.out.println("id:" + id + ",userName:" + name + ",password:" + passsword);

? ? ? ? ? ? }

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }finally {

? ? ? ? ? ? JDBCUtils.close(resultSet,stmt,con);

? ? ? ? }




JDBC批處理

1 Statement批處理

以下是使用語句對象的批處理的典型步驟

1 注冊驅動獲取連接 2 使用 c r e a t e S t a t e m e n t () 方法創(chuàng)建Statement對象。 3 使用 s e t A u t o C o m mit () 將auto-commit設置為false 。 4 使用 a d d B a t c h () 方法在創(chuàng)建的語句對象上添加您喜歡的SQL語句到批處理中扳肛。 5 在創(chuàng)建的語句對象上使用 e x e c u t e B a t c h () 方法執(zhí)行所有SQL語句傻挂。 6 使用 c o m mit () 方法提交所有更改。 7 釋放資源

Statement stmt = conn.createStatement();

conn.setAutoCommit(false);

String SQL = "INSERT INTO Employees (id, first, last, age) " + ? ? ? ? ? ? "VALUES(200,'Zia', 'Ali', 30)";? stmt.addBatch(SQL);

String SQL = "INSERT INTO Employees (id, first, last, age) " + ? ? ? ? ? ? "VALUES(201,'Raj', 'Kumar', 35)";

stmt.addBatch(SQL);?

String SQL = "UPDATE Employees SET age = 35 " + ? ? ? ? ? ? "WHER3;

sstmt.addBatch(SQL);

?int[] count = stmt.executeBatch();

conn.commit();

1.2 PrepareStatement批處理

1. 使用占位符創(chuàng)建SQL語句挖息。 2. 使用 p r e p a r e S t a t e m e n t () 方法創(chuàng)建PrepareStatement對象金拒。 3. 使用 s e t A u t o C o m mit () 將auto-commit設置為false 。 4. 使用 a d d B a t c h () 方法在創(chuàng)建的語句對象上添加您喜歡的SQL語句到批處理中旋讹。 5. 在創(chuàng)建的語句對象上使用 e x e c u t e B a t c h () 方法執(zhí)行所有SQL語句殖蚕。 6. 最后,使用 c o m mit () 方法提交所有更改沉迹。

String SQL = "INSERT INTO Employees (id, first, last, age) " + ? ? ? ? ? ? "VALUES(?, ?, ?, ?)";

PreparedStatemen pstmt = conn.prepareStatement(SQL);

?conn.setAutoCommit(false);

?pstmt.setInt( 1, 400 );?

pstmt.setString( 2, "Pappu" );?

pstmt.setString( 3, "Singh" );?

pstmt.setInt( 4, 33 );

?pstmt.addBatch();

pstmt.setInt( 1, 401 );

pstmt.setString( 2, "Pawan" );

?pstmt.setString( 3, "Singh" );

?pstmt.setInt( 4, 31 );?

?pstmt.addBatch();

事務的四大特點?

Atomicity(原子性)? ? 表示一個事務內的所有操作是一個整體,要么全部成功害驹,要么全部失敗

Consistency(一致性)? ? 表示一個事務內有一個操作失敗時鞭呕,所有的更改過的數(shù)據(jù)都必須回滾到修改前狀態(tài)

Isolation(隔離性)? 事務查看數(shù)據(jù)時數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務修改它之前的狀態(tài)宛官,要么是另一事務修改它 之后的狀態(tài)葫松,事務不會查看中間狀態(tài)的數(shù)據(jù)。

Durability(持久性)

? 持久性事務完成之后底洗,它對于系統(tǒng)的影響是永久性的腋么。

#開啟事務 START TRANSACTION;??

? ?# connection.setAutoCommit(false);?

UPDATE account SET money=money-1000 WHERE id=1;?

UPDATE account SET money=money+1000 WHERE id=2;

?#提交事務 COMMIT;#connection.commit();

?#connection.rollback();

事務隔離級別

? SQL標準定義了4類隔離級別,包括了一些具體規(guī)則亥揖,用來限定事務內外的哪些改變是可見的珊擂,哪些 是不可見的。低級別的隔離級一般支持更高的并發(fā)處理费变,并擁有更低的系統(tǒng)開銷摧扇。

Read Uncommitted(讀取未提交內容)

? ? ? 在該隔離級別,所有事務都可以看到其他未提交事務的執(zhí)行結果挚歧。本隔離級別很少用于實際應用扛稽, 因為它的性能也不比其他級別好多少。讀取未提交的數(shù)據(jù)滑负,也被稱之為臟讀(Dirty Read)在张。

Read Committed(讀取提交內容)

? ? ? 這是大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個 事務只能看見已經提交事務所做的改變矮慕。這種隔離級別出現(xiàn)不可重復讀(Nonrepeatable Read)問題帮匾, 因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果凡傅。

? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? e1.printStackTrace();? ? ? ? ? ? }? ? ? ? }finally {? ? ? ? ? ? if(pstat1!=null){? ? ? ? ? ? ? ? try {? ? ? ? ? ? ? ? ? ? pstat1.close();? ? ? ? ? ? ? ? } catch (SQLException e) {? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? if(pstat2!=null){? ? ? ? ? ? ? ? try {? ? ? ? ? ? ? ? ? ? pstat2.close();? ? ? ? ? ? ? ? } catch (SQLException e) {? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? if(connection!=null){? ? ? ? ? ? ? ? try {? ? ? ? ? ? ? ? ? ? connection.close();? ? ? ? ? ? ? ? } catch (SQLException e) {? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? }

#開啟事務 START TRANSACTION; ? ? # connection.setAutoCommit(false); UPDATE account SET money=money-1000 WHERE id=1; UPDATE account SET money=money+1000 WHERE id=2; #提交事務 COMMIT;#connection.commit(); #回滾 ROLLBACK; #connection.rollback();

Repeatable Read 可重讀

? ? ? 這是MySQL的默認事務隔離級別辟狈,它確保同一事務的多個實例在并發(fā)讀取數(shù)據(jù)時,會看到同樣的數(shù) 據(jù)行。不過理論上哼转,這會導致另一個棘手的問題:幻讀(Phantom Read)明未。簡單的說,幻讀指當用戶讀 取某一范圍的數(shù)據(jù)行時壹蔓,另一個事務又在該范圍內插入了新行趟妥,當用戶再讀取該范圍的數(shù)據(jù)行時,會發(fā) 現(xiàn)有新的“幻讀” 行佣蓉。InnoDB和Falcon存儲引擎通過多版本并發(fā)控制(MVCC披摄,Multiversion Concurrency Control)機制解決了該問題。

Serializable 可串行化

? ? ? ? 這是最高的隔離級別勇凭,它通過強制事務排序疚膊,使之不可能相互沖突,從而解決幻讀問題虾标。簡言之寓盗, 它是在每個讀的數(shù)據(jù)行上加上共享鎖。在這個級別璧函,可能導致大量的超時現(xiàn)象和鎖競爭傀蚌。效率最低的。

? ? ? 這四種隔離級別采取不同的鎖類型來實現(xiàn)蘸吓,若讀取的是同一個數(shù)據(jù)的話善炫,就容易發(fā)生問題。

總結

1 批處理

Statement實現(xiàn)批處理

? stat.addBatch(sql);// insert? update? delete

? stat.executeBatch();

PreparetedStatement

? pstat.addBatch();

? pstat.executeBatch();

? pstat.clearBatch();

2 jdbc操作大數(shù)據(jù)

? 大文本 tinytext? text? mediumtext? longtext

? setAsciiStream();

? setCharacterStream();

? setBinaryStream();

? 二進制tinyblob? blob? mediunblob? longblob

? setBinaryStream();

3 事務:一組要么同時執(zhí)行成功,要么同時失敗的SQL語句。是數(shù)據(jù)庫操作的一個不能分割執(zhí)行單元误甚。

四個特性:

原子性? A: 不能分割

一致性 C:事務執(zhí)行前后保持一致

隔離型 I: 事務與事務之間對數(shù)據(jù)的讀取控制

持久性 D:事務提交或回滾之后,永久保存數(shù)據(jù)庫舅桩。

4? 修改隔離級別

java代碼更改隔離級別

5 保存點

SavePoint

? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? }? ? ? ? }? ? }

#修改事務的隔離級別: SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE] #查看事務隔離級別 SELECT @@tx_isolation;

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);




IO流

定義

IO流用來處理設備之間的數(shù)據(jù)傳輸

Java對數(shù)據(jù)的操作是通過流的方式

Java用于操作流的類都在IO包中

流按流向分為兩種:輸入流,輸出流雨膨。I/O

流按操作類型分為兩種:

字節(jié)流 : 字節(jié)流可以操作任何數(shù)據(jù),因為在計算機中任何數(shù)據(jù)都是以字節(jié)的形式存儲的

字符流 : 字符流只能操作純字符數(shù)據(jù)擂涛,比較方便。

IO流常用父類

字節(jié)流的抽象父類:

InputStream

OutputStream

字符流的抽象父類:

Reader

Writer

每次讀取一個字節(jié)的速度實在是太慢了,實際開發(fā)中根本無法使用

所以,java為我們提供了一次獲取多個字節(jié)的方法, read(byte[] b), 允許一次獲取一個數(shù)組長度的字節(jié)

available()方法

這個方法可以幫我們獲取資源中剩余的長度

public static void main(String[] args) throws Exception {


FileInputStream fis = new FileInputStream("d:\\騎在銀龍的背上.mp3");

FileOutputStream fos = new FileOutputStream("d:\\音樂副本.mp3");

//創(chuàng)建一個和資源文件大小相同的字節(jié)數(shù)組

//byte[] bs = new byte[fis.available()];

//fis.read(bs);

//fos.write(bs);

? ? byte[] bs = new byte[1024];

? ? int len;

? ? //數(shù)據(jù)傳輸消耗的時間遠遠大于java內部數(shù)據(jù)處理的時間

? ? while((len=fis.read(bs))!=-1){

? ? ? ? for (int i = 0; i < len; i++) {

? ? ? ? ? ? bs[i] = (byte)(bs[i]^123);

? ? ? ? }

? ? ? ? fos.write(bs,0,len);

? ? }

fis.close();

fos.close();

}

所有我們可以創(chuàng)建一個和資源文件大小相等長度小數(shù)組來裝載數(shù)據(jù)

字節(jié)輸入緩沖流(BufferedInputStream)

定義

我們都知道單個字節(jié)的讀取是效率非常低下的, 所以我們使用了小數(shù)組的方法進行流的讀取和寫入

java中已經幫我們實現(xiàn)了, 這就是緩沖區(qū)的概念, 也是一次性讀取一個數(shù)組,然后將這個數(shù)組放入內存中供我們使用

緩沖流只是一個殼,實際還是字節(jié)流在工作

構造方法

BufferedInputStream(InputStream in)

創(chuàng)建一個BufferedInputStream 并保存其參數(shù), 即輸入in ,一遍將來使用

BuffferedInputStream(InputStream in , int size)

創(chuàng)建一個具有指定緩沖區(qū)大小的BufferedInputStream并保存其參數(shù), 即輸入流in,以便將來使用

常用方法

read() : 一次讀取一個字節(jié)

read(byte[] b, int off, int len) : 從此字節(jié)輸入流中給定偏移量處開始各字節(jié)讀取到指定的byte數(shù)組中

close() : 關閉并釋放資源,實際關閉的是內部真正工作的字節(jié)流

注意事項

BufferedInputStream內部建立一個緩沖區(qū)域,在讀取文件的時候, 一次性讀取大量的字節(jié), 緩沖到緩沖區(qū)當中, 然后再反給我們, 看著沒有變化, 區(qū)別在于一個直接操作硬盤, 一個是操作內存, 效率不可相提并論

字節(jié)輸出緩沖流(BufferedOutputStream)

定義

單個字節(jié)的寫入是效率及其低下的, 所以我們使用了小數(shù)組的形式進行寫入, 一次寫入一個數(shù)組的數(shù)據(jù)

java中給我們提供了輸出緩沖區(qū)流,將我們寫的字節(jié)先存放到一個小數(shù)組中,等數(shù)組滿了之后再寫入到本地去

在流關閉之前, 會有一次寫入動作, 這樣就避免了最后一次讀取時, 緩沖區(qū)沒有滿不能寫入的問題

構造方法

BufferedOutputStream(OutputStram out)

創(chuàng)建一個新的緩沖輸出流聊记,以將數(shù)據(jù)寫入指定的底層輸出流

BufferedOutputStream(OutputStream out, int size)

創(chuàng)建一個新的緩沖輸出流撒妈,以將具有指定緩沖區(qū)大小的數(shù)據(jù)寫入指定的底層輸出流

常用方法

write(int b) : 將指定的字節(jié)寫入此緩沖流的輸出流

write(byte[] b, int off, int len) : 將指定byte數(shù)組中從偏移量off開始的len個字節(jié)吸入此緩沖流的輸入流

flush() : 刷新此緩沖流的輸出流

close() : 關閉流,并釋放資源

演示

publicstaticvoidmain(String[]args)throwsException{


? ? FileOutputStreamfos=newFileOutputStream("d:\\ddd.txt");

? ? BufferedOutputStreambos=newBufferedOutputStream(fos);

? ? for(inti=0;i<10000;i++) {

? ? ? ? bos.write(97);

? ? }


? ? bos.close();

}

注意事項

緩沖流就一個殼, 他不能實際和本地文件建立連接, 本質還是通過InputStream和OutputStream來工作

將一個文件夾復制到另一個地方


public static void copy(String srcname,String target) throws Exception{

File srcFile = new File(srcname);

File targetFile = new File(new File(target),srcFile.getName());

targetFile.mkdir();

File[] files = srcFile.listFiles();

if(files!=null){

for (File file : files) {

if (file.isFile()) {

FileInputStream fis = new FileInputStream(file);

//targetFile+文件名

File file2 = new File(targetFile,file.getName());

FileOutputStream fos = new FileOutputStream(file2);

byte[] bs = new byte[1024*8];

int len ;

while((len=fis.read(bs))!=-1){

fos.write(bs,0,len);

}

fis.close();

fos.close();

}else{

copy(file.getAbsolutePath(),targetFile.getAbsolutePath());

}

}

}

}

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市排监,隨后出現(xiàn)的幾起案子狰右,更是在濱河造成了極大的恐慌,老刑警劉巖舆床,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棋蚌,死亡現(xiàn)場離奇詭異嫁佳,居然都是意外死亡,警方通過查閱死者的電腦和手機谷暮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進店門蒿往,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人湿弦,你說我怎么就攤上這事瓤漏。” “怎么了颊埃?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵蔬充,是天一觀的道長。 經常有香客問我班利,道長饥漫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任罗标,我火速辦了婚禮趾浅,結果婚禮上,老公的妹妹穿的比我還像新娘馒稍。我一直安慰自己,他們只是感情好浅侨,可當我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布纽谒。 她就那樣靜靜地躺著,像睡著了一般如输。 火紅的嫁衣襯著肌膚如雪鼓黔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天不见,我揣著相機與錄音澳化,去河邊找鬼。 笑死稳吮,一個胖子當著我的面吹牛缎谷,可吹牛的內容都是我干的。 我是一名探鬼主播灶似,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼列林,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了酪惭?” 一聲冷哼從身側響起希痴,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎春感,沒想到半個月后砌创,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虏缸,經...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年嫩实,在試婚紗的時候發(fā)現(xiàn)自己被綠了刽辙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡舶赔,死狀恐怖扫倡,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情竟纳,我是刑警寧澤撵溃,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站锥累,受9級特大地震影響缘挑,放射性物質發(fā)生泄漏。R本人自食惡果不足惜桶略,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一语淘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧际歼,春花似錦惶翻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旭愧,卻和暖如春颅筋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背输枯。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工议泵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桃熄。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓先口,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蜻拨。 傳聞我的和親對象是個殘疾皇子池充,可洞房花燭夜當晚...
    茶點故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內容