- This ORM data access
- Database changes reflect to NSIndexPath that will refresh UI automatically
- Read write concurrency
- You could preload a few properties, when you access others properties than load from disk
- LRU objects cache
- Based on FMDB
There six main classes in BLDatabase
BLBaseDBObject
Represents table and attributesBLDatabase
Represents database. Used for creating data connectionsBLDatabaseConnection
Used for creating transactionBLDatabaseTransaction
Used for insert, update, delete, find objectsBLFetchedResultsController
Used for refreshing UI automaticallyBLFetchRequest
Represents sql
Create a class extend from BLBaseDBObject
#import "BLBaseDBObject.h"
BL_ARRAY_TYPE(BLAccount);
@interface BLAccount : BLBaseDBObject
@property (nonatomic, copy) NSString *accessToken;
@property (nonatomic, copy) NSString *userId;
@property (nonatomic, copy) NSString *nickname;
@property (nonatomic, strong) BLAccount *relationship; // one to one
@property (nonatomic, copy) NSString *relationshipId; // name must be [relationshipname] + [Id]
@property (nonatomic, strong) NSArray<BLAccount> *relationships; // one to many
@property (nonatomic, copy) NSArray *relationshipsIds; // name must be [relationshipname] + [Ids]
@end
self.database = [BLDatabase defaultDatabase];
[self.database setSchemaVersion:1
withMigrationBlock:^(BLDatabaseReadWriteTransaction *transaction, NSUInteger oldSchemaVersion) {
[BLTestObject createTableAndIndexIfNeededInTransaction:transaction];
[BLAccount createTableAndIndexIfNeededInTransaction:transaction];
}];
// async find
BLDatabaseConnection *connection = [self.database connection];
[connection asyncReadWriteTransaction:^(BLDatabaseReadWriteTransaction *readWriteTransaction, BOOL *rollback) {
NSArray *result = [BLTestObject findObjectsInTransaction:readWriteTransaction
withRequest:nil];
}];
// sync find
BLDatabaseConnection *connection = [self.database connection];
[connection syncReadWriteTransaction:^(BLDatabaseReadWriteTransaction *readWriteTransaction, BOOL *rollback) {
NSArray *result = [BLTestObject findObjectsInTransaction:readWriteTransaction
withRequest:nil];
}];
// async transaction
BLDatabaseConnection *connection = [database connection];
[connection asyncReadWriteTransaction:^(BLDatabaseReadWriteTransaction *readWriteTransaction, BOOL *rollback) {
//...
}];
// sync transaction
BLDatabaseConnection *connection = [database connection];
[connection syncReadWriteTransaction:^(BLDatabaseReadWriteTransaction *readWriteTransaction, BOOL *rollback) {
//...
}];
BLDatabaseConnection *connection = [database connection];
[connection syncReadWriteTransaction:^(BLDatabaseReadWriteTransaction *readWriteTransaction, BOOL *rollback) {
// insert
BLTestObject *object = [BLTestObject new];
object.age = 20;
object.name = @"test";
[readWriteTransaction insertObject:object];
// update
object.age = 30;
[readWriteTransaction updateObject:object];
// delete
[readWriteTransaction deleteObject:object];
}];
// one to one
BLDatabaseConnection *connection = [database connection];
[connection syncReadWriteTransaction:^(BLDatabaseReadWriteTransaction *readWriteTransaction, BOOL *rollback) {
BLAccount *account = [BLAccount new];
NSString *uniqueId = account.uniqueId;
BLAccount *account1 = [BLAccount new];
NSString *uniqueId1 = account1.uniqueId;
account.relationship = account1;
account1.relationship = account;
[readWriteTransaction insertObjects:@[account, account1]];
}];
// one to many
BLDatabaseConnection *connection = [database connection];
[connection syncReadWriteTransaction:^(BLDatabaseReadWriteTransaction *readWriteTransaction, BOOL *rollback) {
BLAccount *account = [BLAccount new];
NSString *uniqueId = account.uniqueId;
BLAccount *account1 = [BLAccount new];
NSString *uniqueId1 = account1.uniqueId;
BLAccount *account2 = [BLAccount new];
NSString *uniqueId2 = account2.uniqueId;
account.relationships = (NSArray<BLAccount> *)@[account1, account2];
[readWriteTransaction insertObjects:@[account, account1, account2]];
}];
// create
BLFetchRequest *request = [BLFetchRequest new];
request.sqlAfterWhere = nil;
request.fieldNames = @[@"name", @"groupName"];
request.sortTerm = @"name:1";
BLDatabaseConnection *connection = [database connection];
BLFetchedResultsController *controller = [[BLFetchedResultsController alloc] initWithFetchRequest:request
groupByKeyPath:@"groupName"
groupAscending:YES
objectClass:[BLTestObject class]
inConnection:connection];
controller.delegate = self;
[controller performFetch];
[self.tableView reloadData];
// refresh ui
- (void)controller:(BLFetchedResultsController *)controller didChangeWithIndexSet:(NSIndexSet *)indexSet forChangeType:(BLFetchedResultsChangeType)type
{
if (type == BLFetchedResultsChangeInsert) {
[self.tableView insertSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
} else if (type == BLFetchedResultsChangeDelete) {
[self.tableView deleteSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (void)controller:(BLFetchedResultsController *)controller didChangeWithIndexPaths:(NSArray *)indexPaths forChangeType:(BLFetchedResultsChangeType)type
{
if (type == BLFetchedResultsChangeInsert) {
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft];
} else if (type == BLFetchedResultsChangeUpdate) {
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
} else if (type == BLFetchedResultsChangeDelete) {
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
}
}
- (void)controllerWillChangeContent:(BLFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(BLFetchedResultsController *)controller
{
[self.tableView endUpdates];
}