项目用到本地数据存储 使用FMDB心得

一,创建一个单例管理FMDB

单例头文件包含
#import <Foundation/Foundation.h>
#import "FMDB.h" // FMDB头文件
#import "PAStudentModel.h" // 需要做存储属性Model
@interface PAFMDBManager : NSObject
/**
 数据库线程  增删改查都在这个线层做处理 保证线层安全和数据操作有效性  如在外部线层做数据存储太过频繁出现闪退 可能是抢占资源造成的
 */
@property(nonatomic,strong) FMDatabaseQueue *dbQueue;

@end

******************************一道华丽的分割线来到PAFMDBManager.m***************************

#import "PAFMDBManager.h"
// 数据库-----表名 根据业务需要,创建一张或者多张表 这里避免对一张表操作多故分成两张表
// 表名1 用来保存要识别成功考生
#define kStudentTB2     @"StudentTable2"
// 表名1 用做上传识别考生
#define kUploadStudentTB     @"UploadStudentTB"

// 数据库-----字段
#define P_VECTOR           @"P_F1" //特征向量
#define kName              @"name" // 学生姓名
#define kCardID            @"CardID"
#define kcandidate_num     @"candidate_num"
#define kseat_num          @"seat_num"
#define kRoomID            @"RoomID"
#define klocation_ID       @"location_ID"
#define kExamination_no     @"Examination_no"
#define kStudentImage      @"StudentImage" // 表2学生现场照
#define kCardImage         @"CardImage" //表1证件照
#define kCardImageNamePath @"CardImageNamePath" // 证件照路径
#define kImageTime         @"ImageTime"
#define kStudentKey        @"StudentKey"
#define kStudentState       @"StudentState"
#define kexam_time           @"exam_time"
#define kexam_date          @"exam_date"
#define ksimilarity      @"similarity" // 学生相似度
@implementation PAFMDBManager
/**
 *  单例的初始化
 */
+ (instancetype)shareInstance{
    
    static PAFMDBManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        manager = [[PAFMDBManager alloc] init];

    });
    
    return manager;
}
/**
 *  在初始化 init中 创建数据表
 */
- (instancetype)init{
    if (self = [super init]) {
       // 1. 获取沙盒路径
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        // 拼接数据的名称
        path = [path stringByAppendingPathComponent:@"StudentSqlDB.db"];
        self.dbQueue  = [FMDatabaseQueue databaseQueueWithPath:path];
        
        
        // 会通过block传递队列中创建好的数据库  里面字段不必理会根据业务需求字段比较多  需要注意的是 这里面不同字段类型怎样存储  --------> 如kStudentState 用 INTEGER 这个类型存储,kCardImage ------> blob 这个image 用data类型来存储
        [self.dbQueue inDatabase:^(FMDatabase *db) {
            // 4. 创建表  计数表
            NSString *sql2 = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@ TEXT PRIMARY KEY NOT NULL,%@ TEXT , %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT,%@ TEXT,%@ TEXT, %@ TEXT,%@ blob, %@ INTEGER,%@ blob, %@ TEXT, %@ TEXT,%@ TEXT,%@ TEXT,%@ TEXT)",kStudentTB2,kStudentKey, kCardID,P_VECTOR, kName,kcandidate_num,kseat_num,kRoomID,klocation_ID,kImageTime,kStudentImage,kexam_time,kexam_date,kExamination_no,kStudentState,kCardImage,kBatch,room_id,ksimilarity,kCardImageNamePath,kwgclqt];

            // 执行语句
            if (![db executeUpdate:sql2]) {
                NSLog(@"建表2失败");
            }else{
                NSLog(@"建表2成功! 存储现场采集学生照片");
            }
              // 上传表
                NSString *sql3 = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@ TEXT PRIMARY KEY NOT NULL,%@ TEXT ,%@ TEXT , %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT, %@ TEXT,%@ TEXT,%@ TEXT, %@ TEXT,%@ blob, %@ INTEGER,%@ blob,%@ INTEGER,%@ INTEGER,%@ TEXT,%@ TEXT,%@ TEXT,%@ TEXT,%@ TEXT,%@ TEXT,%@ TEXT,%@ TEXT,%@ TEXT)",kUploadStudentTB,kTimesKey,kStudentKey, kCardID,P_VECTOR, kName,kcandidate_num,kseat_num,kRoomID,klocation_ID,kImageTime,kStudentImage,kexam_time,kexam_date,kExamination_no,kStudentState,kCardImage,kuploadState,kStudentIndex,kdisciplineType,kdisciplineCode,kdisciplineStr,room_id,kwgclh,kwgclqt,ksimilarity,kCardImageNamePath,kBatch];
            // 执行语句
            if (![db executeUpdate:sql3]) {
                NSLog(@"建表3失败");
            }else{
                NSLog(@"建表3成功! 上传数据表!");
            }

        }];
    }
    
    return self;
}
@end

二,下面开始增删改查 基本操作

#pragma mark 增 -----> 外部调用传入需要存储的学生Model
- (void)insert1:(NSString *)tableName WithStudent:(PAStudentModel *)student{
    if ([tableName isEqualToString:kStudentTB2]){
        
        [self.dbQueue inDatabase:^(FMDatabase *db) {
            NSData* imgData = UIImageJPEGRepresentation(student.StudentImage, 0.3);
            NSData *imageCardDate = UIImageJPEGRepresentation(student.CardImage, 0.3);
            NSString *sql = [NSString stringWithFormat:@"INSERT INTO %@ ( %@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@) VALUES ( ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?, ?, ?, ?,?,?,?)", kStudentTB2,kStudentKey, kCardID,P_VECTOR, kName,kcandidate_num,kseat_num,kRoomID,klocation_ID,kImageTime,kexam_time,kexam_date,kStudentImage,kExamination_no,kStudentState,kCardImage,kBatch,room_id,ksimilarity,kCardImageNamePath];
            
            if (![db executeUpdate:sql, student.StudentKey,student.CardID,student.vector,student.StudentName,student.candidate_num,student.seat_num,student.RoomID,student.location_ID,student.ImageTime,student.exam_time,student.exam_date,imgData,student.Examination_no,@(student.StudentState),imageCardDate,student.Batch,student.roomid,student.similarity,student.CardImageNamePath]) {
                NSLog(@"插入表2失败");
                
            }else{
                NSLog(@"插入表2成功");
            }
        }];
    }
}

#pragma mark  改------> 更新表中 学生状态 存储的学生图片
- (void)updateStudent2Table:(NSString *)TableName  WithStudent:(PAStudentModel *)Model State:(NSInteger)StateIndex {
    
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"UPDATE %@ SET %@ = ?,%@ = ?,%@ = ?, %@ = ? WHERE %@ = ?", kStudentTB2, kStudentState,kStudentImage,kImageTime ,ksimilarity,kStudentKey];
        NSData* imgData = UIImageJPEGRepresentation(Model.StudentImage, 0.3);
        if (![db executeUpdate:sql, @(StateIndex),imgData, Model.ImageTime,Model.similarity,Model.StudentKey]) {
            NSLog(@"%@更新状态失败",kStudentTB2);
        }else{
            NSLog(@"%@更新状态成功",kStudentTB2);
        }
    }];
}

#pragma mark 查-------> 查找某个考室中状态 1 和 3 的所有学生 返回学生模型便于外部逻辑处理
- (NSMutableArray *)findAllStudentExamination_no:(NSString *)Examination_no  StudentRomm_ID:(NSString *)Room_ID exam_Date:(NSString *)exam_date
{
    __block NSMutableArray *studentList = [[NSMutableArray alloc] init];
        [self.dbQueue inDatabase:^(FMDatabase *db) {
            NSString *sql = [NSString stringWithFormat:@"SELECT * FROM UploadStudentTB where %@ = '%@' and %@ = '%@' and %@ = '%@' and StudentState in (1, 3) group by CardID order by imagetime ", kRoomID, Room_ID, kExamination_no, Examination_no,kexam_date,exam_date];
            FMResultSet *result = [db executeQuery:sql];
        while ([result next]){
   
                PAStudentModel *student = [[PAStudentModel alloc] init];
                student.StudentName = [result stringForColumn:kName];
                student.CardID = [result stringForColumn:kCardID];
                student.vector = [result stringForColumn:P_VECTOR];
                student.seat_num = [result stringForColumn:kseat_num];
                student.candidate_num = [result stringForColumn:kcandidate_num];
                student.location_ID = [result stringForColumn:klocation_ID];
                student.RoomID = [result stringForColumn:kRoomID];
                student.ImageTime = [result stringForColumn:kImageTime];
                NSData *imageData = [result dataForColumn:kStudentImage];
                student.StudentImage = [UIImage imageWithData:imageData];
                student.StudentKey = [result stringForColumn:kStudentKey];
                student.StudentState = [result intForColumn:kStudentState];
                NSData *CardimageData = [result dataForColumn:kCardImage];
                student.CardImage = [UIImage imageWithData:CardimageData];
                student.Examination_no =  [result stringForColumn:kExamination_no];
                student.exam_date = [result stringForColumn:kexam_date];
                student.exam_time = [result stringForColumn:kexam_time];
//                student.Batch = [result stringForColumn:kBatch];
                student.roomid = [result stringForColumn:room_id];
                student.similarity = [result stringForColumn:ksimilarity];
            student.CardImageNamePath = [result stringForColumn:kCardImageNamePath];
            student.wgclqt = [result stringForColumn:kwgclqt];

                [studentList addObject:student];
            }
        
        
        [result close];
    }];
    
    return studentList;
}



#pragma mark 查找计数表 某个考室中状态 1 和 3 的最近的7位学生 最新录入的7个学生
- (NSMutableArray *)findAllStudentInStudentExamination_no:(NSString *)Examination_no  StudentRomm_ID:(NSString *)Room_ID exam_Date:(NSString *)exam_date
{
    __block NSMutableArray *studentList = [[NSMutableArray alloc] init];
    
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"SELECT * FROM StudentTable2 where %@ = '%@' and %@ = '%@' and %@ = '%@' and StudentState in (1, 3) group by CardID order by imagetime desc LIMIT 7", kRoomID, Room_ID, kExamination_no, Examination_no,kexam_date,exam_date];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]){
            // 创建新的模型,每行数据就是一个模型
            PAStudentModel *student = [[PAStudentModel alloc] init];
            student.StudentName = [result stringForColumn:kName];
            student.CardID = [result stringForColumn:kCardID];
            student.vector = [result stringForColumn:P_VECTOR];
            student.seat_num = [result stringForColumn:kseat_num];
            student.candidate_num = [result stringForColumn:kcandidate_num];
            student.location_ID = [result stringForColumn:klocation_ID];
            student.RoomID = [result stringForColumn:kRoomID];
            student.ImageTime = [result stringForColumn:kImageTime];
            NSData *imageData = [result dataForColumn:kStudentImage];
            student.StudentImage = [UIImage imageWithData:imageData];
            student.StudentKey = [result stringForColumn:kStudentKey];
            student.StudentState = [result intForColumn:kStudentState];
            NSData *CardimageData = [result dataForColumn:kCardImage];
            student.CardImage = [UIImage imageWithData:CardimageData];
            student.Examination_no =  [result stringForColumn:kExamination_no];
            student.exam_date = [result stringForColumn:kexam_date];
            student.exam_time = [result stringForColumn:kexam_time];
//            student.Batch = [result stringForColumn:kBatch];
            student.roomid = [result stringForColumn:room_id];
            student.similarity = [result stringForColumn:ksimilarity];
            student.CardImageNamePath = [result stringForColumn:kCardImageNamePath];
            student.wgclqt = [result stringForColumn:kwgclqt];

            [studentList addObject:student];
        }
        
        [result close];
    }];
    
    return studentList;
}
#pragma mark 删除某张表  也可以根据创建表时 每条数据的唯一key来删除某一个学生
- (void)removeTable:(NSString *)TableName {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"DELETE FROM %@", TableName];
        if (![db executeUpdate:sql]) {
            NSLog(@"删除失败");
        }else{
            NSLog(@"删除成功");
        }
    }];
}

#pragma mark 在判断某个学生是否存在摸张表中 也可以根据创建表时 每条数据的唯一key来判断
- (BOOL)isExistenceUploadStudentTB:(NSString *)TableName WithColumnName:(NSString *)ColumnName {
    __block BOOL isExist = NO;
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ = ?", TableName,kStudentKey];
        FMResultSet *set = [db executeQuery:sql,ColumnName];
        
        isExist = [set next];
        
        [set close];
    }];
    
    return isExist;
}

#pragma mark 根据key 找到唯一学生
- (NSMutableArray *)findStudentCount:(NSString *)TabelName WithStudent:(NSString *)studentKey{
    
    __block NSMutableArray *studentList = [[NSMutableArray alloc] init];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ = ?", TabelName, kStudentKey];
        FMResultSet *result = [db executeQuery:sql,studentKey];
        
        while ([result next]){
            // 创建新的模型,每行数据就是一个模型
            PAStudentModel *student = [[PAStudentModel alloc] init];
            student.StudentName = [result stringForColumn:kName];
            student.CardID = [result stringForColumn:kCardID];
            student.vector = [result stringForColumn:P_VECTOR];
            student.seat_num = [result stringForColumn:kseat_num];
            student.candidate_num = [result stringForColumn:kcandidate_num];
            student.location_ID = [result stringForColumn:klocation_ID];
            student.RoomID = [result stringForColumn:kRoomID];
            student.ImageTime = [result stringForColumn:kImageTime];
            NSData *imageData = [result dataForColumn:kStudentImage];
            student.StudentImage = [UIImage imageWithData:imageData];
            student.StudentKey = [result stringForColumn:kStudentKey];
            student.StudentState = [result intForColumn:kStudentState];
            NSData *CardimageData = [result dataForColumn:kCardImage];
            student.CardImage = [UIImage imageWithData:CardimageData];
            student.Examination_no =  [result stringForColumn:kExamination_no];
            student.exam_date = [result stringForColumn:kexam_date];
            student.exam_time = [result stringForColumn:kexam_time];
            student.wgclqt = [result stringForColumn:kwgclqt];
            student.wgclh = [result stringForColumn:kwgclh];
            student.similarity = [result stringForColumn:ksimilarity];
            student.CardImageNamePath = [result stringForColumn:kCardImageNamePath];
            student.wgclqt = [result stringForColumn:kwgclqt];

            [studentList addObject:student];
        }
        
        [result close];
    }];
    
    
    return studentList;
}
#pragma mark 找到表   中所有学生
- (NSMutableArray *)findUploadStudentTBAllStudents
{
    
    __block NSMutableArray *studentList = [[NSMutableArray alloc] init];
    
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ = ?", kUploadStudentTB,kuploadState];
        FMResultSet *result = [db executeQuery:sql,@(0)];
        
        while ([result next]){
            PAStudentModel *student = [[PAStudentModel alloc] init];
            student.StudentName = [result stringForColumn:kName];
            student.CardID = [result stringForColumn:kCardID];
            student.vector = [result stringForColumn:P_VECTOR];
            student.seat_num = [result stringForColumn:kseat_num];
            student.candidate_num = [result stringForColumn:kcandidate_num];
            student.location_ID = [result stringForColumn:klocation_ID];
            student.RoomID = [result stringForColumn:kRoomID];
            student.ImageTime = [result stringForColumn:kImageTime];
            student.StudentKey = [result stringForColumn:kStudentKey];
            student.StudentState = [result intForColumn:kStudentState];
            student.roomid = [result stringForColumn:room_id];
            NSData *CardimageData = [result dataForColumn:kCardImage];
            student.CardImage = [UIImage imageWithData:CardimageData];
            NSData *imageData = [result dataForColumn:kStudentImage];
            student.StudentImage = [UIImage imageWithData:imageData];
            student.Batch = [result stringForColumn:kBatch];

            
            student.Examination_no =  [result stringForColumn:kExamination_no];
            student.exam_date = [result stringForColumn:kexam_date];
            student.exam_time = [result stringForColumn:kexam_time];
            student.index = [result intForColumn:kStudentIndex];
            student.disciplineCode = [result stringForColumn:kdisciplineCode];
            student.disciplineType = [result stringForColumn:kdisciplineType];
            student.disciplineStr = [result stringForColumn:kdisciplineStr];
            student.wgclqt = [result stringForColumn:kwgclqt];
            student.wgclh = [result stringForColumn:kwgclh];
            student.similarity = [result stringForColumn:ksimilarity];
            student.CardImageNamePath = [result stringForColumn:kCardImageNamePath];

            [studentList addObject:student];
        }
        
        [result close];
    }];
    return studentList;
}
/**
 *  批量 添加数组数据 并使它们的操作在一个事务中完成 这里是批量操作 不要频繁打开和关闭一个事务  在一个中完成就好 非常省时
 */
- (void)InsterTokStudentTB2:(NSMutableArray *)StudentArr
{
    
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSDate *startTime = [NSDate date];
        [db beginTransaction];
        BOOL isRollBack = NO;
        @try
        {
            for (int i = 0; i<StudentArr.count; i++)
            {
                
                PAStudentModel *student = StudentArr[i];
                
                
                // 判断是否已存在数据库
                NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ = ?", kStudentTB2,kStudentKey];
                FMResultSet *set = [db executeQuery:sql,student.StudentKey];
                bool isExist = [set next];
                [set close];
                
                
                if (!isExist) {
                    
                    //                    [self insert1:@"StudentTable2" WithStudent:student];
                    
                    NSData* imgData = UIImageJPEGRepresentation(student.StudentImage, 0.3);
                    NSData *imageCardDate = UIImageJPEGRepresentation(student.CardImage, 0.3);
                    NSString *sql = [NSString stringWithFormat:@"INSERT INTO %@ ( %@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@,%@) VALUES ( ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?, ?, ?, ?,?,?,?,?)", kStudentTB2,kStudentKey, kCardID,P_VECTOR, kName,kcandidate_num,kseat_num,kRoomID,klocation_ID,kImageTime,kexam_time,kexam_date,kStudentImage,kExamination_no,kStudentState,kCardImage,kBatch,room_id,ksimilarity,kCardImageNamePath,kwgclqt];

                    if (![db executeUpdate:sql, student.StudentKey,student.CardID,student.vector,student.StudentName,student.candidate_num,student.seat_num,student.RoomID,student.location_ID,student.ImageTime,student.exam_time,student.exam_date,imgData,student.Examination_no,@(student.StudentState),imageCardDate,student.Batch,student.roomid,student.similarity,student.CardImageNamePath]) {
                        NSLog(@"插入表2失败");
                        
                    }else{
//                        NSLog(@"插入表2成功");
                    }
                    
                }else{
                    
//                    NSLog(@"该考生已经存在数据库!");
                }
                
                
            }
            
            NSDate *endTime = [NSDate date];
            NSTimeInterval a = [endTime timeIntervalSince1970] - [startTime timeIntervalSince1970];
            NSLog(@"使用事务插入%ld条数据用时%.3f秒",StudentArr.count,a);
            
        }
        @catch (NSException *exception)
        {
            isRollBack = YES;
            [db rollback];
        }
        @finally
        {
            if (!isRollBack)
            {
                [db commit];
            }
        }
        
    }];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容