# JRDB **Repository Path**: qiqb_admin/JRDB ## Basic Information - **Project Name**: JRDB - **Description**: https://github.com/scubers/JRDB.git 仓库克隆 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-10 - **Last Updated**: 2026-09-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # iOS用对FMDB封装 **一个对FMDB进行类Hibernate封装的ios库** [![Build Status](http://img.shields.io/travis/scubers/JRDB/developing.svg?style=flat)](https://travis-ci.org/scubers/JRDB) [![Pod Version](http://img.shields.io/cocoapods/v/JRDB.svg?style=flat)](http://cocoadocs.org/docsets/JRDB/) [![Pod Platform](http://img.shields.io/cocoapods/p/JRDB.svg?style=flat)](http://cocoadocs.org/docsets/JRDB/) [![Pod License](http://img.shields.io/cocoapods/l/JRDB.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0.html) GitHub: [sucbers](https://github.com/scubers) Feedback: [jr-wong@qq.com](mailto:jrwong@qq.com) 有问题或者bug欢迎随时issues我,或者邮件。感谢使用 # 2.0更新 > * 数据库字段名,从默认的_ivar名 改为 property名 : _name -> name * 数据库操作对象获取改为连接池: [JRDBMgr defaultDB] -> [JRDBMgr shareInstance].getHandler * 抛弃缓存功能 * 新增And, Or查询语句 --- # 描述(Description) > - 使用分类的模式,模仿Hibernate,对FMDB进行简易封装 > - 使用协议,不用继承基类,对任意NSObject可以进行入库操作 > - Objective-C(Swift 请移步 [Swift扩展](https://github.com/scubers/JRDBSwift)) --- # 目录(Index) > - [安装](#installationId) - [表操作](#tableId) - [保存](#saveId) - [更新](#updateId) - [删除](#deleteId) - [查询](#queryId) - [链式调用配置](#configurationId) - [关联操作](#linkId) - [宏](#macroId) - [子查询](#subQueryId) - [线程安全](#threadId) # 安装(Installation) ``` pod 'JRDB' ``` --- # 开始(Start) ## JRDBMgr 使用 ### 设置数据库路径 ```objc [[JRDBMgr shareInstance] setDefaultDatabasePath:@"/Users/mac/Desktop/test11.sqlite"]; ``` ### 是否打印sql语句 ```objc [JRDBMgr shareInstance].debugMode = YES; ``` ### 获取处理器 - 从连接池中获取数据库处理器 ```objc [[JRDBMgr shareInstance] getHandler]; ``` ### 关闭数据库 ```objc [[JRDBMgr shareInstance] close]; ``` ### 注册 - 需要使用本库的类都需要注册。 ```objc [[JRDBMgr shareInstance] registerClazzes:@[ [Person class], ]]; ``` ## 表名 默认类名为表明,可以自定义表名,在主类中重写一下方法即可 ```objc + (NSString *)jr_customTableName { return @"my_tableName"; } ``` ## 主键 默认每个对象入库都会持有一个ID `[person ID]` , 作为数据库的主键,库通过这个 `ID` 来识别对象是否与数据库关联,所以不是必要时,不要操作此属性 ### 自定义主键 **不同的业务需求,有可能使用的主键有特定的业务意义,需要自行定义。** 在需要自定义的实体类中实现一下方法 ```objc /// 自定义主键的对应的属性 (需要是属性的全名) + (NSString *)jr_customPrimarykey { return @"name"; // 对应property的属性名 } /// 自定义主键属性值 - (id)jr_customPrimarykeyValue { return self.name; } ``` 通过下面的方法可以获取对应的值 ```objc /** * 如果有自定义主键,则返回自定义主键key,例如 name,若没有实现,则返回默认主键key : @"_ID" */ [Person jr_primaryKey]; /** * 如果有自定义主键,则返回自定义主键的值,如果没有,则返回 [self ID] */ [p jr_primaryKeyValue]; ``` ## 自定义字段名 默认使用Property的属性名进行字段名定义,可以对每个地段进行自定义数据库字段名,在主类中重写以下方法即可 * **无返回字段默认使用property属性名当做数据库列名** ```objc + (NSDictionary *)jr_databaseNameMap { return @{ @"name" : @"db_name", @"age" : @"db_age", @"height" : @"db_height", }; } ``` ## 忽略字段 默认非数据库基本类型都会忽略不入库。 数据库基本类型: - NSString - NSDate - NSData - int, unsigned int, double, float, long..... 非以上类型都会自动忽略不入库。 若有特定需要忽略字段,需要实现一下方法 ```objc /// 忽略age属性,不做入库操作 + (NSArray *)jr_excludePropertyNames { return @[ @"age", ]; } ``` --- # 表操作(TableOperation) ### 建表 `J_CreateTable(Person)` ### 更新表 - 更新表时只会添加字段,不会删除或更新字段名,有需要的话需要自行写sql语句解决 `J_UpdateTable(Person)` ### 删除表 `J_DropTable(Person)` ### 重建表 `J_TruncateTable(Person)` --- # 保存(Save) ```objc BOOL result = J_Insert(p) .InDB([JRDBMgr shareInstance].getHandler) // by Default .Recursive(NO) // by default .Sync(YES) // by default .Transaction(YES) // by default .updateResult; // 执行 // 可以省略为 BOOL result = J_Insert(p).updateResult; // 数组保存,两种 api 自由使用 BOOL result = J_Insert(p1, p2, p3).updateResult; BOOL result = J_Insert(@[p1, p2, p3]).updateResult; ``` --- # 更新 (Update) **更新操作需要提供对象的主键,请确保需要更新的对象都是从数据库查出来的;(也可以手动设置主键让库识别,不建议)** ```objc BOOL result = J_Update(p) .Columns(@[@"age", @"name"]) // 更新指定列 // .Ignore(@[@"age", @"name"]) // 忽略指定列 .InDB([JRDBMgr shareInstance].getHandler) // by default .Recursive(NO) // by default .Sync(YES) // by default .Transaction(YES) // by default .updateResult; // 执行 BOOL result = J_Update(p).Ignore(@[@"phone"]).updateResult; // 更新数组 BOOL result = J_Update(p1, p2).updateResult; BOOL result = J_Update(@[p1, p2, p3]).updateResult; ``` --- # 删除(Delete) **删除操作需要提供对象的主键,请确保需要更新的对象都是从数据库查出来的;(也可以手动设置主键让库识别,不建议)** ```objc // 删除 BOOL result = J_Delete(p) .InDB([JRDBMgr shareInstance].getHandler) // by default .Recursive(NO) // by default .Sync(YES) // by default .Transaction(YES) // by default .updateResult; // 执行 ``` # 查询(Query) ```objc // 条件查询 // And Or 对应Property中的属性名 NSArray = J_Select(Person) // select * from person [where 1=1] .And(@"age").lt(@10) // and age < 10 .Or(@"height").gt(@120) // or height > 120 .Or(@"name").like(@"Wang%") // or name like 'Wang%' .And(@"weight").nq(@200) // and weight <> 200 .list // 普通查询 NSArray *result = J_Select(Person) // 指定查询对象 .Recursive(YES) // 默认 可省略 .Sync(YES) // 默认 可省略 .Desc(NO) // 默认 可省略 .Where(@"name like ? and height > ?") // 对应数据库中的字段名 .Params(@[@"L%", @150]) // 对应条件语句的 ? 可省略 .Group(@"level") // Group 可省略 .Order(@"age") // Order 可省略 .Limit(0, 10) // 分页 start, length 可省略 .list; // 自定义查询 NSArray *result1 = J_SelectColumns(@[@"age", @"name"]) .From([Person class]) .Recursive(YES) // 在自定义查询中不会起作用 .Sync(YES) // 默认 可省略 .Where(@"name like ? and height > ?") // 对应数据库中的字段名 .Params(@[@"L%", @150]) .Group(@"level") // 对应数据库中的字段名 .Order(@"age") // 对应数据库中的字段名 .Limit(0, 10) .Desc(NO) .list; NSUInteger count = J_SelectCount(Person) // 查询哪个类 .Recursive(YES) // 在自定义查询中不会起作用 .Sync(YES) // 默认 可省略 .Where(@"name like ? and height > ?") .Params(@[@"L%", @150]) .Group(@"level") .Order(@"age") .Limit(0, 10) .Desc(NO) .count; ``` # 链式调用配置(Configuration) | 配置 | 功能 |参数类型| |:-------------:|------------| -------- | | InDB | [JRDBMgr shareInstance].getHandler by default;|id\ | | From | 自定义查询时指定的类名
or 子查询的Chain对象 |Class \| JRDBChain * | | Recursive | NO by default;
NO:效率高,
YES:[关联操作](#linkId)效率低|YES or NO| | Transaction | YES by default;
NO:本操作不包含事务,外界需要事务支持
YES:包含事务|YES or NO| | Sync | YES by default;
YES:阻塞本线程,线程安全同步执行数据库操作;
NO:在本线程执行数据库操作,线程不安全 |YES or NO| | Where | Where 后面的条件筛选语句,使用 ?作为参数占位符
使用的字段需要与数据库字段相同| NSString * | | WhereIdIs | 等同于 Where(@" _id = ?")| NSString * | | WherePKIs | 等同于 Where(@"<#primary key#> = ?")| id | | And | And语句,跟着属性名 And(@"name")| NSString | | Or | Or语句,跟着属性名 Or(@"age")| NSString | | eq | eq语句,跟着参数 eq(@10) 相当于SQL语句的 「=」| id | | nq | nq语句,跟着参数 nq(@10) 相当于SQL语句的 「<>」| id | | gt | gt语句,跟着参数 eq(@10) 相当于SQL语句的 「>」| id | | lt | lt语句,跟着参数 eq(@10) 相当于SQL语句的 「<」| id | | gtOrEq | gtOrEq语句,跟着参数 eq(@10) 相当于SQL语句的 「>=」| id | | ltOrEq | ltOrEq语句,跟着参数 eq(@10) 相当于SQL语句的 「<=」| id | | like | like语句,跟着参数 eq(@10) 相当于SQL语句的 「like」| id | | Params | Where 语句占位符对应的参数| NSArray * | | Columns | 更新时候指定更新的列| NSArray * | | Ignore | 更新时指定忽略的列| NSArray * | | Group | group by 字段| NSString * | | Order | order by 字段| NSString * | | Limit | 分页字段 (start, length)| unsigned long, unsigned long | | Desc | NO by default; 是否根据orderby 进行降序 | YES or NO| --- # 关联操作(Link) **描述:当一个类的一个属性为一个实体类,在操作数据库时,通过配置,也可以进行同时操作** 例如:当保存 Person 时,也想同时保存 card 对象, Money数组,以及 children数组, 则可以进行关联操作。需要在对应的类实现一下方法, 并且子对象也需要注册 ```objc // 注册子model类 [[JRDBMgr shareInstance] registerClazzes:@[ [Person class], [Card class], [Money class], ]]; @interface Person : NSObject @property (nonatomic, strong) Card *card; @property (nonatomic, strong) NSMutableArray *money; @property (nonatomic, strong) NSMutableArray *children; @end @implementation /// 单个对象关联 + (NSDictionary> *)jr_singleLinkedPropertyNames { return @{ @"card" : [Card class], }; } /// 数组对象关联 + (NSDictionary> *)jr_oneToManyLinkedPropertyNames { return @{ @"money" : [Money class], @"children" : [Person class], }; } @end ``` ### 关联操作 (保存) ```objc Person *p = [Person new]; Card *c = [Card new]; p.card = c; p.money = @[m1,m2,m3]; p.children = @[p1,p2,p3]; BOOL result = J_Insert(p) .Recursive(YES) // 默认为NO, 需要手动指定关联保存 .updateResult; ``` ### 关联操作(更新) **注意:若子对象都是没有保存过的(既数据库没有的对象),则全部保存。若有已存在对象,不保存不更新。** * 出于更新的操作的随意性比较重,更新时不进行一切关联操作,即更新时,只更新本model相关信息,不更新所有子model的信息。当层级较多的时候,需要从子层级开始一步一步开始更新上来(所以不建议建立太多层级) * 更新本model的信息包括: * 子model的ID会保存(若有) * 子model数组的数量(若子model数组数量发生变更会更新,但是子model的数组不会更到数据库) ``` BOOL result = J_Update(p).Recursive(YES).updateResult; ``` -- ### 关联操作(删除) * 和更新一样,删除时,只会删除本model的信息,不会进行一切关联操作。 * 删除时,会删除一对多的中间表无用信息 ``` BOOL result = J_Delete(p).Recursive(YES).updateResult; ``` --- ### 关联操作(查询) ```objc NSArray *list = J_Select(Person).Recursive(YES).list; ``` --- # 宏(Macro) - 使用宏,让调用变成更智能 - `From([Person class]) --> FromJ(Person)` - `Where(@"name = ?") --> WhereJ(_name = ?)` - `Order(@"name") --> OrderJ(name)` - `Group(@"name") --> GroupJ(name)` - `Params(@[@"jack", @"mark"]) --> ParamsJ(@"jack", @"mark")` - `Ignore(@[@"name", @"age"]) --> IgnoreJ(@"name", @"age")` - `Columns(@[@"name", @"age"]) --> ColumnsJ(@"name", @"age")` ``` // example NSArray *result = J_Select(Person) .WhereJ(name like ? and height > ?) .ParamsJ(@"a%", @100) .GroupJ(h_double) .OrderJ(d_long_long) .list; BOOL result = J_Update(person) .ColumnsJ(J(name), J(age)) // .IgnoreJ(J(name), J(age)) .updateResult; ``` --- # 子查询(SubQuery) ```objc // 正常查询只能先排序再分页,加入子查询,可以先分页,再从子结果中排序 . ie. NSArray *list =J_Select(Person) .From( J_Select(Person).Limit(0, 10) // 放入一个子查询,外部查询则从子查询的结果里继续查询 ).OrderJ(age) .Descend .list; ``` --- # NSObject+JRDB **给NSObject添加分类方法,以方便快捷的方式使用本库的渐变功能** ```objc - (BOOL)jr_saveOrUpdateOnly;// 非关联操作 - (BOOL)jr_saveOrUpdate; // 关联操作 #pragma mark - save - (BOOL)jr_saveOnly; - (BOOL)jr_save; #pragma mark - update - (BOOL)jr_updateOnlyColumns:(NSArray * _Nullable)columns; - (BOOL)jr_updateColumns:(NSArray * _Nullable)columns; - (BOOL)jr_updateOnlyIgnore:(NSArray * _Nullable)Ignore; - (BOOL)jr_updateIgnore:(NSArray * _Nullable)Ignore; #pragma mark - delete + (BOOL)jr_deleteAllOnly; + (BOOL)jr_deleteAll; - (BOOL)jr_deleteOnly; - (BOOL)jr_delete; #pragma mark - select /// 关联查询 + (instancetype _Nullable)jr_findByID:(NSString * _Nonnull)ID; + (instancetype _Nullable)jr_findByPrimaryKey:(id _Nonnull)primaryKey; + (NSArray> * _Nonnull)jr_findAll; /// 非关联查询 + (instancetype _Nullable)jr_getByID:(NSString * _Nonnull)ID; + (instancetype _Nullable)jr_getByPrimaryKey:(id _Nonnull)primaryKey; + (NSArray> * _Nonnull)jr_getAll; ``` --- # 线程安全 **使用本库的数据库,都是阻塞本线程,并且线程安全的,所有操作带有事务。
操作本库管理的数据库时,请使用本库提供的API进行操作,否则有可能产生数据库锁问题** --- # 泛型提示 ![abc](https://raw.githubusercontent.com/scubers/JRDB/master/generic_tip.png) 通过泛型,查询出来后,编译器直接识别结果为对应对象,减少强转操作。 --- # 更多使用 请查看 JRPersistentHandler.h