開始
在這篇教學(xué)中,我們採用 Ubuntu 16.04 系統(tǒng)和 MySQL 5.7。 MySQL 5.7 引進(jìn)了一系列的新功能。其中一個(gè)就是提供了更有效率的儲存 JSON 資料的能力,同時(shí)提供了查詢 JSON 資料內(nèi)部的能力。稍後如果 MySQL 5.7 成為了 Ubuntu 16.04 上預(yù)設(shè)的 MySQL 版本以後,我們將使用 Ubuntu 16.04 作為我們的作業(yè)系統(tǒng)。
如果你還沒安裝 Swift, 你可以使用 apt-get 方式來安裝。請參閱這篇文章的說明安裝。 2016 年 9 月底,蘋果也開始在 Ubuntu16.04 上編譯 Swift 的鏡像。請查看?Swift.org?以取得更多的資訊。
建立資料庫
我們把資料庫命名為?swift_test, 指派的使用者是?swift,密碼是?swiftpass,如果你熟悉 MySQL,你應(yīng)該知道需要執(zhí)行?GRANT ALL ON swift_test.*?進(jìn)行授權(quán)。
下面是這部分的命令:
# sudo mysql ... mysql> create user swift; Query OK, 0 rows affected (0.00 sec) mysql> create database swift_test; Query OK, 1 row affected (0.00 sec) mysql> grant all on swift_test.* to 'swift'@'localhost' identified by 'swiftpass'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) mysql> quit Bye
創(chuàng)建Swift 套件
現(xiàn)在開始正式進(jìn)行編碼,首先創(chuàng)建一個(gè)套件:
# mkdir swift_mysql # swift package init --type executable
編寫Package.swift 檔案:
import PackageDescription let package = Package( name: "swift_mysql", dependencies:[ .Package(url:"https://github.com/vapor/mysql", majorVersion:1) ] )
第二步,我們使用一些輔助的工具程式碼來產(chǎn)生一些隨機(jī)的數(shù)據(jù),填充到資料庫中。在 Sources 目錄下加入 utils.swift 檔案並在裡面加入以下內(nèi)容:
import Glibc class Random { static let initialize:Void = { srandom(UInt32(time(nil))) return () }() } func randomString(ofLength length:Int) -> String { Random.initialize let charactersString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" let charactersArray:[Character] = Array(charactersString.characters) var string = "" for _ in 0..<length { string.append(charactersArray[Int(random()) % charactersArray.count]) } return string } func randomInt() -> Int { Random.initialize return Int(random() % 10000) }
Vapor MySQL
接下來是真正的程式碼,我們的 main.swift 檔案使用了 Vapor MySQL 模組。
連接資料庫
將以下程式碼新增以下程式碼到?Sources/main.swift?中:
import Glibc import MySQL var mysql:Database do { mysql = try Database(host:"localhost", user:"swift", password:"swiftpass", database:"swift_test") try mysql.execute("SELECT @@version") } catch { print("Unable to connect to MySQL: \(error)") exit(-1) }
以上程式碼設(shè)定資料庫並且處理 mysql。建構(gòu)器?Database(host:String, user:String, password:String, database:String)?一目了然。
語句?try mysql.execute("SELECT @@version”)?是用來測試保證我們連接正確,並且成功連接到了資料庫。如果 do 程式碼區(qū)塊運(yùn)作無錯(cuò)誤,接下來就可以開始操作資料庫了!
整數(shù)和字串
所有對 MySQL 的呼叫都會透過?execute(_:String)?方法。要注意的是這個(gè)方法和一些抽象API 的方法不同,例如?.create(table:String, ...)?或?.insert(table:String, …。execute?取得原始的SQL 語句並傳給MySQL 連接器。
do { try mysql.execute("DROP TABLE IF EXISTS foo") try mysql.execute("CREATE TABLE foo (bar INT(4), baz VARCHAR(16))") for i in 1...10 { let int = randomInt() let string = randomString(ofLength:16) try mysql.execute("INSERT INTO foo VALUES (\(int), '\(string)')") } // Query let results = try mysql.execute("SELECT * FROM foo") for result in results { if let bar = result["bar"]?.int, let baz = result["baz"]?.string { print("\(bar)\t\(baz)") } } } catch { print("Error: \(error)") exit(-1) }
查詢結(jié)果也是使用的?execute(_:String)?方法。
Node 類型是 Vapor 中的數(shù)據(jù)結(jié)構(gòu),用于轉(zhuǎn)化為不同的類型。你可以從這里獲取更多的信息。使用 Node 類型來表達(dá) MySQL 可以方便的轉(zhuǎn)換成對應(yīng)的 Swift 類型。比如:let bar = result["bar"]?.int 給我們一個(gè)整型。
繼續(xù)
接著我們來看一些更復(fù)雜的例子,比如創(chuàng)建一個(gè)表,包含了 MySQL 的 DATE, POINT 和 JSON 數(shù)據(jù)類型。我們的表名叫 samples。
do { try mysql.execute("DROP TABLE IF EXISTS samples") try mysql.execute("CREATE TABLE samples (id INT PRIMARY KEY AUTO_INCREMENT, created_at DATETIME, location POINT, reading JSON)") // ... Date // ... Point // ... Sample // ... Insert // ... Query } catch { print("Error: \(error)") exit(-1) }
要插入一個(gè)日期到數(shù)據(jù)庫中,需要正確的 SQL 語句:
// ... Date let now = Date() let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" // MySQL will accept this format let created_at = formatter.string(from:date)
接下來使用 Swift 元組來創(chuàng)建一個(gè) POINT:
// ... Point let location = (37.20262, -112.98785) // latitude, longitude
最后,我們來處理 MySQL 5.7 中新的 JSON 數(shù)據(jù)類型,此外我們使用了 Jay 包來快速將一個(gè) Swift 字典 [String:Any] 轉(zhuǎn)換為 JSON 格式的字符串。
// ... Sample let sample:[String:Any] = [ "heading":90, "gps":[ "latitude":37.20262, "longitude":-112.98785 ], "speed":82, "temperature":200 ]
提示:你不需要顯式在 Package.swift 中聲明對 Jay 的依賴,因?yàn)樵?MySQL 的包中已經(jīng)包含了這個(gè)依賴。接下來我們把 JSON 數(shù)據(jù)轉(zhuǎn)換為 String,用來拼湊 MySQL 語句。
let sampleData = try Jay(formatting:.minified).dataFromJson(any:sample) // [UInt8] let sampleJSON = String(data:Data(sampleData), encoding:.utf8)
這樣我們就有了 date, point 和 JSON 字符串(sample) 了, 現(xiàn)在添加數(shù)據(jù)到 sample 表中:
// ... Insert let stmt = "INSERT INTO samples (created_at, location, sample) VALUES ('\(created_at)', POINT\(point), '\(sampleJSON)')" try mysql.execute(stmt)
請注意我們在處理 POINT 時(shí)候,使用了一些技巧。在對 (point) 展開為字符串 (37.20262, -112.98785) 后,完整的字符串是 POINT(37.20262, -112.98785),這是 MySQL 所需要的數(shù)據(jù),整個(gè)語句的字符串如下:
INSERT INTO samples (created_at, location, sample) VALUES ('2016-09-21 22:28:44', POINT(37.202620000000003, -112.98784999999999), '{"gps":{"latitude":37.20262,"longitude":-112.98785},"heading":90,"speed":82,"temperature":200}')
獲取結(jié)果
警告:在寫這篇文章的時(shí)候(2016-09-22), Vapor MySQL 1.0.0 有一個(gè) bug:在讀取 POINT 數(shù)據(jù)類型時(shí)會 crash 掉,所以不得不在下面代碼中加入 do 代碼塊,然后不使用 select 語句。我們在 Vapor MySQL 中記錄了這個(gè) issue,等這個(gè) issue 修復(fù)以后,我們將更新文章。
在下面的例子中,我們將使用 MySQL 5.7 中引入對 JSON 數(shù)據(jù)內(nèi)部的查詢特性,使用 SELECT … WHERE 查詢 JSON 數(shù)據(jù)。在這里查詢的是 samples 表中 JSON 數(shù)據(jù)類型 sample中、speed 字段大于 80 的數(shù)據(jù)。
// ... 查詢 let results = try mysql.execute("SELECT created_at,sample FROM samples where JSON_EXTRACT(sample, '$.speed') > 80") for result in results { if let sample = result["sample"]?.object, let speed = sample["speed"]?.int, let temperature = sample["temperature"]?.int, let created_at = result["created_at"]?.string { print("Time:\(created_at)\tSpeed:\(speed)\tTemperature:\(temperature)") } }
這里做一些說明。JSON_EXTRACT 函數(shù)是用來 返回從 JSON 文檔中的數(shù)據(jù),根據(jù)傳入的路徑參數(shù)選擇文檔中滿足條件的數(shù)據(jù)。在本例中,我們解包了列 sample 中的 speed 值。
為了循環(huán)處理結(jié)果,我們使用了 for result in results 語句,接著使用 if let 語句驗(yàn)證結(jié)果數(shù)據(jù)。首先使用?let sample = result["sample"]?.object?獲取一個(gè)字典,對應(yīng) MySQL 中的 JSON 文檔,這是一句關(guān)鍵的代碼!Vapor MySQL 庫并沒有返回一個(gè) String,而 String 還需進(jìn)行 JSON 的解析。這個(gè)解析工作庫已經(jīng)幫你做了,所以你可以直接使用 sample 字典啦。
剩下的 let 語句給了我們 speed,temperature 和 created_at。注意 created_at 在 MySQL 中是 DATETIME 類型,我們讀取它為字符串。為了在 Swift 中轉(zhuǎn)換成 Date 類型,需要使用 .date(from:String) 方法加一個(gè) DateFormatter 來做類型轉(zhuǎn)換。
獲取代碼
如果你想直接運(yùn)行代碼,請到?github?上下載我們的代碼。
在任何地方使用?swift build?進(jìn)行編譯,運(yùn)行可執(zhí)行代碼,不要忘了你還需要擁有一個(gè)數(shù)據(jù)庫,用戶名并且授權(quán)通過。

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)
