BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS AccountList (money text, useType text, type text, date text, remark text, accountId INTEGER PRIMARY KEY AUTOINCREMENT);”];
其中
accountId INTEGER PRIMARY KEY AUTOINCREMENT
意为创建名为accounId的主变量 类型为int 可以自动增加 删除后不会重新添加该id
FMDB的FMDatabaseQueue是一个串行队列 保证了所有通过该对象添加的block任务是同步的,保证了线程安全。
对于这个队列是否会先判断有无创建表,需要进一步了解—
多数据写入
错误示范:
// for (int i = 0; i < typeArr.count; i ++) {
// if (i < typeArr.count - 1) {
// [[TABDBTool sharedInstance] addType:typeArr[i] success:^{
//
// } failed:^{
//
// }];
// }
// else {
// [[TABDBTool sharedInstance] addType:typeArr[i] success:^{
// [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"tabIsType"];
// [[NSUserDefaults standardUserDefaults] synchronize];
// [self getData];
// } failed:^{
//
// }];
// }
// }
用事务添加会快很多
// 用事务实现批量添加
- (void)addTypeArr:(NSArray *)typeArr success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
if (typeArr && typeArr.count) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
[db beginTransaction];
BOOL isRollBack = NO;
@try
{
for (NSString *type in typeArr) {
[db executeUpdateWithFormat:@"INSERT INTO TypeList (type) VALUES (%@);", type];
}
}
@catch (NSException *exception) {
isRollBack = YES;
[db rollback];
}
@finally {
if (!isRollBack) {
[db commit];
[self resultWithResult:!isRollBack success:success failed:failed];
}
}
}];
});
}
}
// 另一种写法
__block BOOL flag = NO;
[self.dbQueue inTransaction:^(FMDatabase * _Nonnull db, BOOL * _Nonnull rollback) {
@try
{
for (NSString *type in typeArr) {
flag = [db executeUpdateWithFormat:@"INSERT INTO TypeList (type) VALUES (%@);", type];
}
}
@catch (NSException *exception) {
*rollback = YES;
flag = NO;
}
@finally {
*rollback = !flag;
if (flag) {
[self resultWithResult:flag success:success failed:failed];
}
}
}];
代码示范:
.h
#import <Foundation/Foundation.h>
#import "TABAccountModel.h"
#import "TABTypeModel.h"
#import <FMDB/FMDB.h>
typedef void(^GetDataBlock)(NSMutableArray *array);
typedef void(^TabDbSuccess)(void);
typedef void(^TabDbFailed)(NSString *reason);
@interface TABDBTool : NSObject
@property (nonatomic, strong) FMDatabaseQueue *dbQueue;
+ (TABDBTool *)sharedInstance;
/*
账单表
*/
- (void)addModel:(TABAccountModel *)model success:(TabDbSuccess)success failed:(TabDbFailed)failed;
- (void)deleteModel:(TABAccountModel *)model success:(TabDbSuccess)success failed:(TabDbFailed)failed;
- (void)deleteWithUseType:(NSString *)type success:(TabDbSuccess)success failed:(TabDbFailed)failed;
- (void)getAllModelWithBlock:(GetDataBlock)block failed:(TabDbFailed)failed;
- (void)getModelListWithUseType:(NSString *)type block:(GetDataBlock)block failed:(TabDbFailed)failed;
- (void)getmodelListWithDate:(NSString *)date block:(GetDataBlock)block failed:(TabDbFailed)failed;
- (void)getmodelListWithUseType:(NSString *)type date:(NSString *)date block:(GetDataBlock)block failed:(TabDbFailed)failed;
/*
类型表
*/
- (void)addType:(NSString *)type success:(TabDbSuccess)success failed:(TabDbFailed)failed;
- (void)addTypeArr:(NSArray *)typeArr success:(TabDbSuccess)success failed:(TabDbFailed)failed;
- (void)deleteTypeWithTypeId:(TABTypeModel *)typeModel success:(TabDbSuccess)success failed:(TabDbFailed)failed;
- (void)getAllType:(GetDataBlock)block failed:(TabDbFailed)failed;
@end
.m
#import "TABDBTool.h"
@implementation TABDBTool
+ (TABDBTool *)sharedInstance
{
static TABDBTool *tool = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
tool = [[TABDBTool alloc] init];
});
return tool;
}
- (instancetype)init
{
self = [super init];
if (self) {
NSString *documentFile = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *fileName = [documentFile stringByAppendingPathComponent:@"Account.sqlite"];
NSLog(@"数据库地址: %@", fileName);
self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:fileName];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS AccountList (money text, useType text, type text, date text, remark text, accountId INTEGER PRIMARY KEY AUTOINCREMENT);"];
if (result) {
NSLog(@"创建账单表成功");
}
else {
NSLog(@"创建账单表失败");
}
BOOL resultType = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS TypeList (type text, typeId INTEGER PRIMARY KEY AUTOINCREMENT);"];
if (resultType) {
NSLog(@"创建类型表成功");
}
else {
NSLog(@"创建类型表失败");
}
}];
});
}
return self;
}
- (void)addModel:(TABAccountModel *)model success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
if (model) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
BOOL result = [db executeUpdateWithFormat:@"INSERT INTO AccountList (money, useType, type, date, remark) VALUES (%@, %@, %@, %@, %@);", model.money, model.useType, model.type, model.date, model.remark];
NSLog(@"保存成功");
[self resultWithResult:result success:success failed:failed];
}];
});
}
}
- (void)deleteModel:(TABAccountModel *)model success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
BOOL result = [db executeUpdateWithFormat:@"delete from AccountList where accountId = %ld;", model.accountId];
[self resultWithResult:result success:success failed:failed];
}];
});
}
- (void)deleteWithUseType:(NSString *)type success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
BOOL result = [db executeUpdateWithFormat:@"delete from AccountList where useType = %@;", type];
[self resultWithResult:result success:success failed:failed];
}];
});
}
- (void)updateModel:(TABAccountModel *)model
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
[db executeUpdateWithFormat:@"update AccountList set money = %@ where deviceID = %ld",model.money , model.accountId];
}];
});
}
- (void)getAllModelWithBlock:(GetDataBlock)block failed:(TabDbFailed)failed
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
FMResultSet *resultSet = [db executeQuery:@"select * from AccountList"];
[self getArrayWithResultSet:resultSet block:block failed:failed];
}];
});
}
- (void)getModelListWithUseType:(NSString *)type block:(GetDataBlock)block failed:(TabDbFailed)failed
{
if ([type isEqualToString:@"全部"]) {
[self getAllModelWithBlock:block failed:failed];
}
else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
FMResultSet *resultSet = [db executeQuery:[NSString stringWithFormat:@"select * from AccountList WHERE useType = '%@'", type]];
[self getArrayWithResultSet:resultSet block:block failed:failed];
}];
});
}
}
- (void)getmodelListWithDate:(NSString *)date block:(GetDataBlock)block failed:(TabDbFailed)failed
{
if ([date isEqualToString:@"全部"]) {
[self getAllModelWithBlock:block failed:failed];
}
else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
FMResultSet *resultSet = [db executeQuery:[NSString stringWithFormat:@"select * from AccountList WHERE date LIKE '%@%%';", date]];
[self getArrayWithResultSet:resultSet block:block failed:failed];
}];
});
}
}
- (void)getmodelListWithUseType:(NSString *)type date:(NSString *)date block:(GetDataBlock)block failed:(TabDbFailed)failed
{
if ([type isEqualToString:@"全部"]) {
[self getmodelListWithDate:date block:block failed:failed];
}
else if ([date isEqualToString:@"全部"]) {
[self getModelListWithUseType:type block:block failed:failed];
}
else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
FMResultSet *resultSet = [db executeQuery:[NSString stringWithFormat:@"select * from AccountList WHERE useType = '%@' and date LIKE '%@%%';", type, date]];
[self getArrayWithResultSet:resultSet block:block failed:failed];
}];
});
}
}
- (void)resultWithResult:(BOOL)result success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
if (result) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
success();
});
}
}
else {
if (failed) {
dispatch_async(dispatch_get_main_queue(), ^{
failed(@"");
});
}
}
}
- (void)getArrayWithResultSet:(FMResultSet *)resultSet block:(GetDataBlock)block failed:(TabDbFailed)failed
{
NSMutableArray *array = [NSMutableArray array];
while ([resultSet next]) {
TABAccountModel *model = [[TABAccountModel alloc] init];
model.money = [resultSet stringForColumn:@"money"];
model.useType = [resultSet stringForColumn:@"useType"];
model.type = [resultSet stringForColumn:@"type"];
model.remark = [resultSet stringForColumn:@"remark"];
model.date = [resultSet stringForColumn:@"date"];
model.accountId = [resultSet longForColumn:@"accountId"];
[array addObject:model];
}
[self sortedArray:array];
if (array) {
if (block) {
dispatch_async(dispatch_get_main_queue(), ^{
block(array);
});
}
}
else {
if (failed) {
dispatch_async(dispatch_get_main_queue(), ^{
failed(@"");
});
}
}
}
- (void)sortedArray:(NSMutableArray *)array
{
[array sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd"];
TABAccountModel *model1 = obj1;
TABAccountModel *model2 = obj2;
NSString *str1 = model1.date;
NSString *str2 = model2.date;
if (str1 == nil) {
str1 = @"0000-00-00";
}
if (str2 == nil) {
str2 = @"0000-00-00";
}
NSDate *date1 = [formatter dateFromString:str1];
NSDate *date2 = [formatter dateFromString:str2];
NSComparisonResult result = [date1 compare:date2];
if (result == NSOrderedAscending) { // 降序 NSOrderedAscending;
return YES;
}
else {
return NO;
}
}];
}
#pragma mark -- 类型表部分 --
- (void)addType:(NSString *)type success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
if (type) {
[self getAllType:^(NSMutableArray *array) {
BOOL haveType = NO;
for (TABTypeModel *typeModel in array) {
if ([typeModel.type isEqualToString:type]) {
haveType = YES;
break;
}
}
if (!haveType) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
BOOL result = [db executeUpdateWithFormat:@"INSERT INTO TypeList (type) VALUES (%@);", type];
[self resultWithResult:result success:success failed:failed];
}];
});
}
else {
if (failed) {
failed(@"数据重复");
}
}
} failed:failed];
}
}
// 用事务实现批量添加
- (void)addTypeArr:(NSArray *)typeArr success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
if (typeArr && typeArr.count) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
/*
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
[db beginTransaction];
BOOL isRollBack = NO;
@try
{
for (NSString *type in typeArr) {
[db executeUpdateWithFormat:@"INSERT INTO TypeList (type) VALUES (%@);", type];
}
}
@catch (NSException *exception) {
isRollBack = YES;
[db rollback];
}
@finally {
if (!isRollBack) {
[db commit];
[self resultWithResult:!isRollBack success:success failed:failed];
}
}
}];
*/
// 另一种写法
/**/
__block BOOL flag = NO;
[self.dbQueue inTransaction:^(FMDatabase * _Nonnull db, BOOL * _Nonnull rollback) {
@try
{
for (NSString *type in typeArr) {
flag = [db executeUpdateWithFormat:@"INSERT INTO TypeList (type) VALUES (%@);", type];
}
}
@catch (NSException *exception) {
*rollback = YES;
flag = NO;
}
@finally {
*rollback = !flag;
if (flag) {
[self resultWithResult:flag success:success failed:failed];
}
}
}];
/**/
});
}
}
- (void)deleteTypeWithTypeId:(TABTypeModel *)typeModel success:(TabDbSuccess)success failed:(TabDbFailed)failed
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
BOOL result = [db executeUpdateWithFormat:@"delete from TypeList where typeId = %ld;", typeModel.typeId];
if (result) {
[self deleteWithUseType:typeModel.type success:success failed:failed];
}
}];
});
}
- (void)getAllType:(GetDataBlock)block failed:(TabDbFailed)failed
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbQueue inDatabase:^(FMDatabase * _Nonnull db) {
FMResultSet *resultSet = [db executeQuery:@"select * from TypeList"];
NSMutableArray *array = [NSMutableArray array];
while ([resultSet next]) {
TABTypeModel *model = [[TABTypeModel alloc] init];
model.typeId = [resultSet longForColumn:@"typeId"];
model.type = [resultSet stringForColumn:@"type"];
[array addObject:model];
}
if (array) {
if (block) {
dispatch_async(dispatch_get_main_queue(), ^{
block(array);
});
}
}
else {
if (failed) {
dispatch_async(dispatch_get_main_queue(), ^{
failed(@"");
});
}
}
}];
});
}
@end