0x00 Chapter 5: Fluent & Persisting Models

1.Fluent is Vapor’s ORM or object relational mapping tool.
It’s an abstraction layer between the Vapor application and the database


2.Models are the Swift representation of your data and are used throughout Fluent


3.创建一个使用 Fluent 的新项目
新建一个文件夹,比如 vapor_learn
打开终端 cd 到此文件夹:
打开终端,输入 cd,按个空格,把文件夹 vapor_learn 拖入终端,最后按 Enter
创建一个名为:TILApp 的项目,(Today I Learn)
vapor new TILApp

是否使用 Fluent?
输入:y
数据库使用 Postgres
不使用 Leaf

等待创建完成

以下是日志:

Cloning template...
name: TILApp
Would you like to use Fluent?
y/n> y
fluent: Yes
db: Postgres (Recommended)
Would you like to use Leaf?
y/n> n
leaf: No
Generating project files
+ Package.swift
+ main.swift
+ configure.swift
+ routes.swift
+ Todo.swift
+ CreateTodo.swift
+ .gitkeep
+ TodoController.swift
+ AppTests.swift
+ index.leaf
+ .gitkeep
+ Dockerfile
+ docker-compose.yml
+ .gitignore
+ .dockerignore
Creating git repository
Adding first commit**               **~~**             **~~~~~~**           **~~~~~~~~~~**         **~~~~~~~~~~~~~~**       **~~~~~~~~~~~~~~~~~~**     **~~~~~~~~~~~~~~~~~~~~~~**   **~~~~~~~~~~~~~~~~~~~~~~~~**  **~~~~~~~~~~~~~~~~~~~~~~~~~~** **~~~~~~~~~~~~~~~~~~~~~~~~~~~~****~~~~~~~~~~~~~~~~~~~~~~~~~~~~****~~~~~~~~~~~~~~~~~~~~~++++~~~****~~~~~~~~~~~~~~~~~~~++++~~~** ***~~~~~~~~~~~~~~~++++~~~***  ****~~~~~~~~~~++++~~****    *****~~~~~~~~~*****      *************         _       __    ___   ___   ___  \ \  /  / /\  | |_) / / \ | |_) \_\/  /_/--\ |_|   \_\_/ |_| \ a web framework for Swift    Project TILApp has been created!Use cd 'TILApp' to enter the project directoryUse vapor xcode to open the project in Xcode

看图片更清晰:

使用 cd TILApp 进入项目
使用 vapor xcode 可以在 Xocde 中打开项目

项目结构如下:

TILApp
--- Package.swift
--- Public
--- Resources--- Views--- index.leaf
--- Sources--- App--- Controllers--- TodoController.swift        --- Migrations--- CreateTodo.swift--- Models--- Todo.swift--- configure.swift--- routes.swift                --- Run--- main.swift
--- Tests--- AppTests--- AppTests.swift--- docker-compose.yml--- Dockerfile

看图片更清晰:


4.删除模板中自动生成的一些文件:
依次输入以下 3 个命令:

rm -rf Sources/App/Models/*
rm -rf Sources/App/Migrations/*
rm -rf Sources/App/Controllers/*

删除 configure.swift 中的代码:

app.migrations.add(CreateTodo())

删除 routes.swift 中的代码:

try app.register(collection: TodoController())

5.在 Models 文件夹内,新建模型文件:
Acronym.swift,代表要提交的数据

// 1
final class Acronym: Model {// 2 static let schema = "acronyms"// 3 @IDvar id: UUID?// 4 @Field(key: "short")var short: String@Field(key: "long")var long: String// 5 init() {}// 6 init(id: UUID? = nil, short: String, long: String) {self.id = idself.short = shortself.long = long}
}

// 1. Define a class that conforms to Model.

// 2. Specify the schema as required by Model. This is the name of the table in the database.

// 3. Define an optional id property that stores the ID of the model, if one has been set. This is annotated with Fluent’s @ID property wrapper. This tells Fluent what to use to look up the model in the database

// 4. Define two String properties to hold the acronym and its definition. These use the @Field property wrapper to denote a generic database field. The key parameter is the name of the column in the database
数据库表中的字段,列名称

@ID marks a property as the ID for that table
@Field marks the property of a model as a generic column in the database

// 5. Provide an empty initializer as required by Model. Fluent uses this to initialize models returned from database queries.

// 6. Provide an initializer to create the model as required.


6.在 Migrations 文件夹内,新建文件:
CreateAcronym.swift,用于创建对应的数据库表

// 1
struct CreateAcronym: Migration {// 2func prepare(on database: Database) -> EventLoopFuture<Void> {database.schema("acronyms") // 3.id() // 4.field("short", .string, .required) // 5.field("long", .string, .required)  // 5.create() // 6}// 7func revert(on database: Database) -> EventLoopFuture<Void> {database.schema("acronyms").delete()}
}

// 1. Define a new type, CreateAcronym that conforms to Migration.

// 2. Implement prepare(on:) as required by Migration. You call this method when you run your migrations.

// 3. Define the table name for this model. This must match schema from the model.

// 4. Define the ID column in the database.

// 5. Define columns for short and long. Set the column type to string and mark the columns as required. This matches the non-optional String properties in the model. The field names must match the key of the property wrapper, not the name of the property itself.

// 6. Create the table in the database.

// 7. Implement revert(on:) as required by Migration. You call this function when you revert your migrations. This deletes the table referenced with schema(_:).

继承自 Migration
实现方法 prepare(on:)
为模型创建表,表名 必须和 模型schema 一样
定义 id, short, long 这几个列,指定类型,required 对应 non-optional
.field 的列名,跟 @Fieldkey 对应


7.配置 configure.swift
app.databases.use(_:as:) 方法后添加代码:

app.migrations.add(CreateAcronym())
app.logger.logLevel = .debug
try app.autoMigrate().wait()

8.存储数据模型,需要数据库
测试 PostgreSQL:在 Docker container 里运行 Postgres server
依次 下载安装打开 软件: docker
地址:https://www.docker.com/get-docker

使用终端创建数据库:

docker run --name postgres \-e POSTGRES_DB=vapor_database \-e POSTGRES_USER=vapor_username \-e POSTGRES_PASSWORD=vapor_password \-p 5432:5432 -d postgres

运行一个名为 postgres 的容器
指定 数据库名用户名密码
指定 端口,默认是 5432

检查数据库是否运行:
docker ps

有以下日志,表示成功:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53dc8048acaf postgres “docker-entrypoint.s…” 8 months ago Up 3 seconds 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp postgres

9.最后,提交模型数据到数据库

9.1.让模型 Acronym 遵守 Content 协议
Acronym.swift 最后添加:

extension Acronym: Content {}

Since Acronym already conforms to Codable via Model, you don’t have to add anything else.


9.2.定义 路由:
接收数据,解析 JSON,转成 Acronym 模型,存入数据库

routes.swift 文件中,在 routes 方法内添加:

    // 1app.post("api", "acronyms") { req -> EventLoopFuture<Acronym> in// 2 let acronym = try req.content.decode(Acronym.self)// 3 return acronym.save(on: req.db).map {// 4acronym}}

// 1. Register a new route at /api/acronyms that accepts a POST request and returns EventLoopFuture<Acronym>. It returns the acronym once it’s saved.

// 2. Decode the request’s JSON into an Acronym model using Codable.

// 3. Save the model using Fluent and the database from Request.

// 4. save(on:) returns EventLoopFuture<Void> so use map to return the acronym when the save completes.


10.使用 Rested 提交数据
把代码 运行 起来后,就可以提交数据了

url: http://127.0.0.1:8080/api/acronyms
method: POST
parameters: {"long": "Tomorrow is a good day", "short": "TGD"}

参数提交格式,选择 JSON 形式: JSON-encoded
点击右下角的 Send Request 发起请求
成功后,会返回对应的模型数据,id 字段被赋值了

如下图所示:


11.运行代码
在终端进入到项目的根目录:TILApp
运行命令:vapor run 或者 swift run
会自动下载所有的依赖文件
依赖文件会有很多很多
这一步耗时会 很长很长很长......
你们可能在这 最后一步放弃了

【Vapor】03 Chapter 5: Fluent Persisting Models相关推荐

  1. 【Vapor】07 Chapter 9: Parent-Child Relationships

    0x00 Chapter 9: Parent-Child Relationships 1.Parent-child relationships describe a relationship wher ...

  2. 【Vapor】04 Chapter 6:Configuring a Database

    0x00 Chapter 6:Configuring a Database 1.Vapor has official, Swift-native drivers for: SQLite MySQL P ...

  3. 【Vapor】06 Chapter 8: Controllers

    0x00 Chapter 8: Controllers 上篇文章 把各种路由都写在了 routes.swift 文件内 如果路由事件太多,routes.swift 文件就会越来越大 慢慢地就会变得难以 ...

  4. 【Vapor】05 Chapter 7: CRUD Database Operations

    0x00 Chapter 7: CRUD Database Operations 在 routes.swift 文件内写各种路由 操作数据库的记录 1.create 创建记录,之前的文章已经写过了 需 ...

  5. 【OWA】03安装部署:OWA(Office Web Apps)安装和部署

    前言 在上一篇咱们把owa服务器加入到了域控中,可参考[OWA]02加入域控:将owa服务器加入域控(把计算机加入到域中), 接下来就在这台服务器上安装和配置OWA相关服务 [OWA]01环境准备:通 ...

  6. 【PyTorch】03数据处理

    3 PyTorch数据处理 3.1 数据读取机制DataLoader与Dataset [PyTorch]2.1 DataLoader与Dataset epoch:对训练集的全部数据进行一次完整的训练, ...

  7. 【回归分析】03.回归参数的估计(1)

    文章目录 [回归分析]3. 回归参数的估计(1) 3.1 最小二乘估计 3.2 最小二乘估计的性质 [回归分析]3. 回归参数的估计(1) 3.1 最小二乘估计 用 yyy 表示因变量,x1,x2,⋯ ...

  8. 【2021】03 C++

    小结 开学第一个月. 上个月的计划完成得比较好,看完了<C++ Primer Plus>,考了二级,感觉可拿良好以上,下一步是拿新安江模型和一维水动力学模型练手. 但是,主要任务仍然是整理 ...

  9. 【转】03.Dicom 学习笔记-DICOM C-Get 消息服务

    转自:https://www.jianshu.com/p/c7f5b9fa597c 引言   前篇介绍了 DICOM C-Find 消息服务,本文结合开源 DICOM 库 fo-dicom 详细介绍一 ...

最新文章

  1. 深入理解Oracle RAC 12c 笔记
  2. 【408预推免复习】计算机组成原理之系统总线
  3. matlab波特图带延迟的传递函数,matlab实现波特图
  4. U盘制作linux启动盘
  5. Criteria和DetachedCriteria区别应用
  6. forge不能用java打开_我玩我的世界把java更新了以后,就再也进不了加了forge的版本了,启动器,游戏,forge都重...
  7. python+FFmpeg实现对m3u8文件内的ts视频多线程下载、解密、合并成MP4,并输出。
  8. AutoCAD2019开发配置
  9. 【屏类型结构体定义PanelType】 文档位置:《apiPNL.h》
  10. 半胱氨酸蛋白酶Caspase-8 Inhibitor I, 886462-83-5
  11. 黄金分割搜索法求单峰极小值C++实现
  12. Lightroom“夏日清凉”调色思路
  13. Mac 修改开机登陆界面背景图, 替换沙漠背景图
  14. 数学建模比赛题型划分、常用算法及其适用场景
  15. 黑客入侵电脑?原来只需要简单几步就可以了
  16. HTML在网页上不能显示图片问题
  17. python数据挖掘领域工具包 - wentingtu - 博客园
  18. 未知参数休哈特matlab,一种确定某类工作的人的极限工作时间的方法
  19. oracle大于字符串时间,Oracle
  20. BZOJ1798 【AHOI2009】 seq维护序列 线段树

热门文章

  1. 【react】受控组件与非受控组件
  2. 计算机开机故障报错,笔记本电脑开机报错故障的原因及解决办法
  3. 开源社区JAVA视频网盘分享
  4. 报表示例——用Jasper report实现MongoDB join
  5. Thymeleaf 详解
  6. Kingston U盘枚举过程翻译
  7. PyCharm2019.1.3的安装教程
  8. MBR和GPT分区表有什么区别
  9. 从big.LITTE到DynamIQ
  10. 您可以在PlayStation 4上使用的30种语音命令