Vapor奇幻之旅(05 Fluent)
在上一篇Vapor奇幻之旅(04Routing)中我介紹了Routing的寫法,作為一個web應用,資料庫是必不可少的,而Fluent則是管理資料的一個抽象層,可以支援資料庫的增刪改查等操作,預設的FluentProvider支援sqlite資料庫,也就是說在沒有任何資料庫配置的情況下,可以通過Fluent Provider中的記憶體資料庫來快速載入SQLite資料庫,這樣做的好處是可以輕鬆的進行介面測試。
目前Vapor支援的資料庫如下:
資料庫型別 | Key | Package | Class | 是否來自官方 |
---|---|---|---|---|
Memory | memory | Fluent Provider | Fluent.MemoryDriver | Yes |
SQlite | sqlite | Fluent Provider | Fluent.SQLiteDriver | Yes |
MySQL | mysql | MySQLProvider | MySQLDriver.Driver | Yes |
PostgreSQL | postgresql | PostgreSQLProvider | PostgreSQLDriver.Driver | No |
MongoDB | N/A | MongoProvider | N/A | No |
對於大型資料庫官方只有支援到MySQL,稍顯遺憾,開發團隊最近都在進行Vapor 3的開發,相信不久後就可以有更多的資料庫型別支援了,而且由於Fluent的抽象的特性,只要有相應的驅動,適配任何資料庫我想只是時間問題。
既然是抽象層,我們先不管用啥資料庫,可以先把我們的資料模型搭建起來。
我想給我的網站加一段名人名言,於是我建立一個名為Quotes的模型,程式碼如下:
import Vapor
import FluentProvider
import HTTP
/// 名人名言
final class Quotes: Model {
// 這個屬效能讓Fluent儲存額外的資訊,如這個model的id
let storage = Storage()
//***下面是表中的屬性***
/// 作者
let author: String
/// 內容
let content: String
/// 描述
let description: String
/// 資料庫中列的名字
struct Keys {
static let id = "id"
static let author = "author"
static let content = "content"
static let description = "description"
}
// MARK: 初始化Fluent
/// 初始化Quotes
required init(row: Row) throws {
author = try row.get(Quotes.Keys.author)
content = try row.get(Quotes.Keys.content)
description = try row.get(Quotes.Keys.description)
}
// 序列化Quotes到資料庫
func makeRow() throws -> Row {
var row = Row()
try row.set(Quotes.Keys.author, author)
try row.set(Quotes.Keys.content, content)
try row.set(Quotes.Keys.description, description)
return row
}
}
我們的model有了,下面就該聯絡一下資料庫了,Fluent 提供了一個Preparation協議,原始碼如下:
/// A preparation prepares the database for
/// any task that it may need to perform during runtime.
public protocol Preparation {
/// The prepare method should call any methods
/// it needs on the database to prepare.
static func prepare(_ database: Database) throws
/// The revert method should undo any actions
/// caused by the prepare method.
///
/// If this is impossible, the `PreparationError.revertImpossible`
/// error should be thrown.
static func revert(_ database: Database) throws
}
其中prepare方法是讓資料庫做好準備的方法,比如新建table,而revert方法則是對prepare做的操作進行回滾操作,比如刪除table。
另外,JSON也是網路通訊常用的資料格式,模型通常也需要轉換為JSON串,或者需要解析json串到模型。JSON庫為我們提供了JSONConvertible協議,demo如下
extension Quotes: JSONConvertible {
convenience init(json: JSON) throws {
self.init(
author: try json.get(Quotes.Keys.author),
content: try json.get(Quotes.Keys.content),
description: try json.get(Quotes.Keys.description)
)
}
func makeJSON() throws -> JSON {
var json = JSON()
try json.set(Quotes.Keys.id, id)
try json.set(Quotes.Keys.author, author)
try json.set(Quotes.Keys.content, content)
try json.set(Quotes.Keys.description, description)
return json
}
}
在寫這個extension之前,還需要在mode裡新增一個初始化方法:
/// 名人名言
final class Quotes: Model {
...
// MARK: 初始化Fluent
init(author: String, content: String, description: String) {
self.author = author
self.content = content
self.description = description
}
...
}
模型已經建好了,那麼作為一個資料庫模型,怎麼能少了增刪改查呢,藥藥藥,切克鬧,增刪改查來一套:
這裡我們需要開始寫Controller了,在controller資料夾內建立一個QuotesController.swift的檔案:
import Vapor
import FluentProvider
struct QuotesController {
func addRoutes(to drop: Droplet) {
let quots = drop.grouped("api","quots")
}
}
然後在Config+Setup.swift中準備好新建立的model:
private func setupPreparations() throws {
preparations.append(Quotes.self)
}
接下來在建立一個Routers+Quotes.swift的檔案並新增QuotesController的routs.
Routers+Quotes.swift:
import Vapor
extension Droplet {
func setupQuotes() {
let quotsController = QuotesController()
quotsController.addRoutes(to: self)
}
}
最後在Droplet+Setup.swift中新增setupQuotes()方法:
@_exported import Vapor
extension Droplet {
public func setup() throws {
setupQuotes()
}
}
現在就可以在我們的controller裡面寫增刪改查了:
import Vapor
import FluentProvider
struct QuotesController {
func addRoutes(to drop: Droplet) {
let quots = drop.grouped("api","quots")
//新增一個新的quots
quots.post("create", handler: createQuots)
//查詢所有的quotes
quots.get(handler: allQuotes)
// 更新quotes
quots.post("update", handler: updateQuotes)
// 刪除quotes
quots.post("delete", handler: deleteQuotes)
}
/// 新增一個新的quots
func createQuots(_ req: Request) throws -> ResponseRepresentable {
guard let json = req.json else {
throw Abort.badRequest
}
let quots = try Quotes(json: json)
try quots.save()
return quots
}
/// 查詢所有的quots
func allQuotes(_ req: Request) throws -> ResponseRepresentable {
let quots = try Quotes.all()
return try quots.makeJSON()
}
/// 更新quotes
func updateQuotes(_ req: Request) throws -> ResponseRepresentable {
guard let json = req.json else {
throw Abort.badRequest
}
let id: Int = try json.get("id")
if let quots = try Quotes.find(id) {
try quots.update(json: json)
}
return try Quotes.all().makeJSON()
}
// 刪除quotes
func deleteQuotes(_ req: Request) throws -> ResponseRepresentable {
guard let json = req.json else {
throw Abort.badRequest
}
let id: Int = try json.get("id")
if let quots = try Quotes.find(id) {
try quots.delete()
}
return try Quotes.all().makeJSON()
}
}
還需要在Quotes中加入一個update方法,並把引數改成var
/// 名人名言
final class Quotes: Model {
/// 作者
var author: String
/// 內容
var content: String
/// 描述
var description: String
...
}
extension Quotes {
func update(json: JSON) throws {
self.author = try json.get(Quotes.Keys.author)
self.content = try json.get(Quotes.Keys.content)
self.description = try json.get(Quotes.Keys.description)
try self.save()
}
}
現在我們的增刪改查就已經完成了,下面cmd+r執行程式,用Rested測試介面:
由於預設的資料庫是基於記憶體載入的,重新執行程式則會清空,如果想要儲存資料到伺服器,你需要使用持續化的資料庫,如MySQL、PostgreSQL以及MongoDB,後面我會對這幾個資料庫操作一一介紹。
關於Vapor其他知識,可以參考以下文章:
Vapor奇幻之旅(01開始)
Vapor奇幻之旅(02部署)
Vapor奇幻之旅(03上手)
Vapor奇幻之旅(04Routing)
Vapor奇幻之旅(05 Fluent)
Vapor奇幻之旅(06 PostgreSQL)
Vapor奇幻之旅(07 連線服務端PostgreSQL)
Vapor奇幻之旅(08 連線服務端MongoDB)
Vapor奇幻之旅(09 連線MySQL)
希望你對我的教程能夠喜歡,你們的贊是我持續的動力,歡迎加入QQ群參與互動:431296189
相關文章
- vapor fluent[sqlite] relationsVaporSQLite
- 牧羊少年奇幻之旅
- 程式碼界的超級英雄:GitHub的奇幻冒險之旅Github
- 聊聊 VaporVapor
- 搞事情之 Vapor 初探Vapor
- 水壩水流3D視覺化:探索自然力量的數字奇幻之旅3D視覺化
- 重啟React Native老專案的奇幻之旅:填坑實錄與解決方案分享React Native
- 創意無限,視覺絢麗—開啟Adobe After Effects 2024(Ae2024)的奇幻之旅視覺
- PyQt-Fluent-Widgets:一個 Fluent Design 風格的元件庫QT元件
- Vapor如何配置MySQL資料庫VaporMySql資料庫
- chap8-fluent pythonPython
- Swift Web 開發之 Vapor – 路由(二)SwiftWebVapor路由
- Fluent-UI 一套受 Fluent Design System 啟發的 React 元件庫UIReact元件
- fluent python是什麼意思Python
- Laravel 生態系統Forge Vapor Nova EnvoyerLaravelVapor
- Swift Web 開發之 Vapor – 模版 Leaf(三)SwiftWebVapor
- FluentAspects -- 基於 Fluent API 的 AopAPI
- wavesurfer fluent-ffmpeg提取音訊音訊
- Swift vapor3 - Async-非同步處理SwiftVapor非同步
- 【計算講談社】第六講|三星堆奇幻之旅:只有雲端計算才能帶來的體驗
- Fluent-Validator 業務校驗器
- Swift web服務框架Vapor 學習資源整理SwiftWeb框架Vapor
- C# 使用Fluent API 建立自己的DSLC#API
- 使用 Swift 和 Vapor 構建區塊鏈伺服器SwiftVapor區塊鏈伺服器
- <OFFER05> 05_ReplaceSpaces
- 奇幻RPG(人物構建 與 Abstract Factory模式)模式
- 05
- Kubernetes官方java客戶端之八:fluent styleJava客戶端
- 上雲十年:阿里雲的奇幻漂流阿里
- 智慧體的奇幻漂流之“成都摺疊”篇智慧體
- 智子: Vue Vapor年底釋出alpha版本,如果有資金支援VueVapor
- Bytom側鏈Vapor原始碼淺析-節點出塊過程Vapor原始碼
- QFluentWidgets: 基於 C++ Qt 的 Fluent Design 元件庫C++QT元件
- 比較開源日誌:Logstash、FluentD 和 Fluent Bit
- 流暢的Python-Fluent Python簡要書評Python
- java 05Java
- 05、springSpring
- EF Core中通過Fluent API完成對錶的配置API
- 用fluent-validator,進行Java服務端驗證Java服務端