ActiveSQLite
ActiveSQLite 是 SQLite.Swift 的一个助手。它可以让您轻松使用 SQLite.Swift。
名为 Reed 下载器 的项目使用了 ActiveSQLite。
功能
- 支持 SQLite.swift 的所有功能。
- 自动创建表。自动添加 id、created_at、updated_at 列。
- 从查询 SQL 中自动设置模型的属性值
- 将表的名称映射到模型的名称,将属性的名称映射到列的名称
- 支持事务和异步操作
- 灵活的、可链式调用、延迟执行的查询层
- 查询使用 String 或 SQLite.swift 的 Expression
- 日志级别
- 运行时编码到 Codable 编码
- 完整的面向协议编程
- 表关系
- 缓存和错误值
示例
运行项目中的 ActiveSQLiteTests 目标。
使用
import ActiveSQLite
class Product:ASModel{
var name:String = ""
var price:NSNumber = NSNumber(value:0.0)
var desc:String?
var publish_date:NSDate?
}
//save
let product = Product()
product.name = "iPhone 7"
product.price = NSNumber(value:599)
try! product.save()
//Query
let p = Product.findFirst("name",value:"iPhone")
//or
let name = Expression<String>("name")
let p = Product.findAll(name == "iPhone").first
//id = 1, name = iPhone 7, price = 599, desc = nil, publish_date = nil, created_at = 1498616987587.237, updated_at = 1498616987587.237,
//Update
p.name = "iPad"
try! p.update()
//Delete
p.delete()
入门
要在目标源文件中使用ActiveSQLite类或结构,首先导入ActiveSQLite
模块。
import ActiveSQLite
连接到数据库
ASConfigration.setDefaultDB(path:"db file path", name: "default db name")
//If you want a other db
ASConfigration.setDB(path: "other db file path", name: "other db name")
必须设置默认数据库路径。
构建类型安全的SQL
ActiveSQLite Swift类型 |
SQLite.swift Swift类型 |
SQLite SQLite类型 |
SQLite默认值 如果不使用可选属性 |
---|---|---|---|
NSNumber |
Int64 |
INTEGER |
0 |
NSNumber |
Double |
REAL |
0.0 |
String |
String |
TEXT |
"" |
nil |
nil |
NULL |
NULL |
SQLite.Blob |
BLOB |
||
NSDate |
Int64 |
INTEGER |
0 |
The NSNumber Type maps with two SQLite.swift's Swift Types. They are Int64 and Double. The default type is Int64. You can override doubleTypes() function of ASModel to mark properties are Double Type.
class Product:ASModel{
var name:String = ""
var price:NSNumber = NSNumber(value:0.0)
var desc:String?
var publish_date:NSDate?
override func doubleTypes() -> [String]{
return ["price"]
}
}
ActiviteSQLite maps NSDate to Int64 of SQLite.swift. You can map NSDate to String by looking Custom Types of Documentation of SQLite.swift
创建表
ActiveSQLite自动创建表并添加"id"。创建代码如下
try db.run(products.create { t in
t.column(id, primaryKey: true)
t.column(Expression<NSDate>("created_at"), defaultValue: NSDate(timeIntervalSince1970: 0))
t.column(Expression<NSDate>("updated_at"), defaultValue: NSDate(timeIntervalSince1970: 0))
t.column(...)
})
// CREATE TABLE "Products" (
// "id" INTEGER PRIMARY KEY NOT NULL,
// created_at INTEGER DEFAULT (0),
// created_at INTEGER DEFAULT (0),
// ...
// )
"created_at"和"updated_at"列的单位是ms。
从ActiveSQLite 0.4.0到0.4.1
ActiveSQLite 0.4.0可以使用3种类型来定义属性:T、T!、T?
ActiveSQLite 0.4.1使用2种类型来定义属性:T、T?
类型 | 0.4.0 | 0.4.1 |
---|---|---|
T |
非nil |
非nil |
T! |
非nil |
可以为nil。用T?替换 |
T? |
可以为nil |
可以为nil |
主键id |
是T!类型 |
是T?类型。 |
如果您想找到数据库列的默认值,请查看本文件中的第一个表格。
映射器
您可以自定义表名、列名,并阻止保存某些属性到数据库。
1. 数据库名。
如果您使用一个数据库,只需设置setDefaultDB(path:name:)即可,无需做任何操作。如果您将表设置在其他数据库中,必须重写dbName。
ASConfigration.setDefaultDB(path:"db file path", name: "default db name")
ASConfigration.setDB(path: "other db file path", name: "other db name")
override class var dbName:String?{
return "other db name"
}
2. 表名。
默认表名与类名相同,无需做任何操作。如果您想使用不同的名称,必须重写nameOfTable。
// Set table name to "ProductTable"
override class var nameOfTable: String{
return "ProductTable"
}
3. 列名。
默认列名与属性名相同,无需做任何操作。如果您想使用不同的名称,必须重写mapper()。
override func mapper() -> [String:String]{
return ["property_name":"column_name"];
}
如果您想让主键不是"id",可以使用如下方式:
override class var PRIMARY_KEY:String{
return "_id"
}
override func mapper() -> [String:String]{
return ["id":"_id"]
}
4. 临时属性。
临时属性尚未保存到数据库。
override class func transientTypess() -> [String]{
return ["isSelected"]
}
ActiveSQLite只能将(String,NSNumber,NSDate)类型的属性保存到数据库。不属于这些类型的属性将不会保存到数据库,它们是临时属性。
5. 自动创建 "created_at" 和 "updated_at" 列。
只需覆盖isSaveDefaulttimestamp,不做任何事情,父类ASModel已经定义了 "created_at" 和 "updated_at" 属性。
override class var isSaveDefaulttimestamp:Bool{
return true
}
表格约束条件
如果您想自己设置自定义列,只需设置model实现CreateColumnsProtocol,并确认创建columns函数。然后ActiveSQLite将不会自动创建列。确保模型映射的属性名与列匹配。
class Users:ASModel,CreateColumnsProtocol{
var name:String = ""
var email:String = ""
var age:Int?
func createColumns(t: TableBuilder) {
t.column(Expression<NSNumber>("id"), primaryKey: true)
t.column(Expression<String>("name"),defaultValue:"Anonymous")
t.column(Expression<String>("email"), , check: email.like("%@%"))
}
}
查看更多关于SQLite.swift的表格约束条件文档文档。
插入行
有三个函数用于插入行。它们是
插入一个。
func insert()throws ;
插入多个。
class func insertBatch(models:[ASModel])throws ;
保存方法。
插入或更新。如果id == nil,则插入。如果id != nil,则更新。
func save() throws;
例如
let u = Users()
u.name = "Kevin"
try! u.save()
var products = [Product]()
for i in 1 ..< 8 {
let p = Product()
p.name = "iPhone-\(i)"
p.price = NSNumber(value:i)
products.append(p)
}
try! Product.insertBatch(models: products)
有关ActiveSQLite的更多源代码或示例,请参阅SQLite.swift的插入行文档。
更新行
更新有三种策略。
1. 通过属性更新。
首先修改模型的属性,然后保存()或更新()或更新批()。
p.name = "zhoukai"
p.save()
2. 通过字符串值更新。
//Update one
u.update("name",value:"3ds")
u.update(["name":"3ds","price":NSNumber(value:199)])
//Update more
Product.update(["name": "3ds","price":NSNumber(value:199)], where: ["id": NSNumber(1)])
2. 通过设置器更新。
更新一个Product对象到数据库。
//Update one
p.update([Product.price <- NSNumber(value:199))
//Update more
Product.update([Product.price <- NSNumber(value:199), where: Product.name == "3ds")
有关更多源代码和ActiveSQLite示例,请参阅文档 更新行文档 和 设置器文档,这些文档均位于SQLite.swift。
选择行
可以使用findFirst来查找一行,使用findAll来查找多行。
以"find"开头名称的方法是类方法。
1. 通过属性查找。
let p = Product.findFirst("name",value:"iWatch")
let ps = Product.findAll("name",value:"iWatch",orders:["price",false])
2. 通过表达式查找。
let id = Expression<NSNumber>("id")
let name = Expression<String>("name")
let arr = Product.findAll(name == "iWatch")
let ps = Product.findAll(id > NSNumber(value:100), orders: [Product.id.asc])
可链式查询
链式查询风格的方法是属性方法。
let products = Product().where(Expression<NSNumber>("code") > 3)
.order(Product.code)
.limit(5)
.run()
别忘了执行run()。
查看ActiveSQLite的源代码和更复杂查询的示例,请参阅SQLite.swift的《构建复杂查询》文档Building Complex Queries
表达式
当执行更新和选择SQL语句时,SQLite.swift使用Expression来替换'where' SQL。要查看更复杂的表达式,请参阅filtering-rows
删除行
//1. Delete one row
try? product.delete()
//2. Delete all rows
try? Product.deleteAll()
//3. Delete by Expression and chains.
try? Product().where(Expression<NSNumber>("code") > 3)
.runDelete()
事务
我建议将所有插入、更新、删除和修改表代码放入ActiveSQLite.save块中。一个块代表一个事务。
ActiveSQLite.save({
var products = [Product]()
for i in 0 ..< 3 {
let p = Product()
p.name = "iPhone-\(i)"
p.price = NSNumber(value:i)
products.append(p)
}
try Product.insertBatch(models: products)
let u = Users()
u.name = "Kevin"
try u.save()
}, completion: { (error) in
if error != nil {
debugPrint("transtion failed \(error)")
}else{
debugPrint("transtion success")
}
})
异步操作
ActiveSQLite.saveAsync也包含一个事务函数。
ActiveSQLite.saveAsync({
.......
}, completion: { (error) in
......
})
更改模式
重命名表和增加列
步骤1.必须更改模型以使用新的列和新表名。
class Product{
var name:String!
var newColumn:String!
override class var nameOfTable: String{
return "newTableName"
}
}
步骤2.在数据库版本更新时执行 alter table sql。
let db = DBConnection.sharedConnection.db
if db.userVersion == 0 {
ActiveSQLite.saveAsync({
try Product.renameTable(oldName:"oldTableName",newName:"newTableName")
try Product.addColumn(["newColumn"])
}, completion: { (error) in
if error == nil {
db.userVersion = 1
}
})
}
更多关于 SQLite.swift 的架构更改,请参见 架构更改
索引
let name = Expression<String>("name")
Product.createIndex(name)
Product.dropIndex(name)
关于 SQLite.swift 文档中索引的更多信息,请参见 索引
删除表
Product.dropTable()
日志记录
有4个日志级别:debug、info、warn、error。默认日志级别为info。设置日志级别的示例
//1. Set log level
ASConfigration.logLevel = .debug
//2. Set db path
ASConfigration.dbPath = "..."
确保在设置数据库路径之前设置日志级别。
需求
- iOS 8.0+
- Xcode 10.2
- Swift 5
安装
Cocoapods
ActiveSQLite 通过 CocoaPods 提供。为了安装它,只需将以下行添加到您的 Podfile 中
pod "ActiveSQLite"
作者
周凯文
- 给我发邮件:[email protected]
- 在 Facebook 上联系我: wumingapie
- 在 微信&QQ 上联系我: 358545592
许可证
ActiveSQLite 受 MIT 许可证保护。有关更多信息,请参阅 LICENSE 文件。