简体   繁体   English

Swift 5.2 Xcode 11.4 Vapor 4.0.0 我应该如何在我的 model 中编码 PK?

[英]Swift 5.2 Xcode 11.4 Vapor 4.0.0 how should I code the PK in my model?

My Package.swift file looks like:我的Package.swift文件如下所示:

.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-rc"),
.package(url: "https://github.com/vapor/fluent.git", from: "4.0.0-rc"),
.package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0-rc")

My config.swift file looks like:我的config.swift文件如下所示:

app.databases.use(.postgres(
    hostname: Environment.get("DATABASE_HOST") ?? "localhost",
    username: Environment.get("DATABASE_USERNAME") ?? "postgres",
    password: Environment.get("DATABASE_PASSWORD") ?? "secret",
    database: Environment.get("DATABASE_NAME") ?? "mydb2"
), as: .psql)

My model looks like:我的 model 看起来像:

import Fluent
import Vapor


final class Complaint: Model, Content {

    static let schema = "cw_complaint5"

    @ID(key: .id)
    var id: UUID?

    @Field(key: "issue_description")
    var issue_description: String

    // etc.
    init() { }
}

In Xcode, the project builds OK, and this GET route runs OK:在 Xcode 中,项目构建正常,此GET路由运行正常:

http://localhost:8080/complaint

But when I run the POST route, I get an error in the response body:但是当我运行POST路由时,响应正文中出现错误:

{
    "error": true,
    "reason": "Value of type 'UUID' required for key 'id'."
}

In Vapor 3, the POST route worked fine for both inserting a new row (omit the ID in the JSON request body) and updating an existing row.在 Vapor 3 中, POST路由对于插入新行(省略 JSON 请求正文中的 ID)和更新现有行都很好。 The table description on PostgreSQL 11.3 looks like: PostgreSQL 11.3 上的表描述如下:

mydb2=# \d+ cw_complaint5
                                              Table "public.cw_complaint5"
        Column        |          Type           | Collation | Nullable | Default | Storage  | Stats target | Description 
----------------------+-------------------------+-----------+----------+---------+----------+--------------+-------------
 id                   | integer                 |           | not null |         | plain    |              | 
 row                  | smallint                |           |          |         | plain    |              | 
 document_number      | integer                 |           | not null |         | plain    |              |
...etc...
county_id            | integer                 |           |          |         | plain    |              | 
 city_id              | integer                 |           |          |         | plain    |              | 
 operator_id          | integer                 |           |          |         | plain    |              | 
Indexes:
    "cw_complaint5_pkey" PRIMARY KEY, btree (id)
Check constraints:
    "cw_complaint5_row_check" CHECK ("row" >= 0)
Foreign-key constraints:
    "cw_complaint5_city_id_fkey" FOREIGN KEY (city_id) REFERENCES cw_city5(id)
    "cw_complaint5_county_id_fkey" FOREIGN KEY (county_id) REFERENCES cw_county5(id)
    "cw_complaint5_operator_id_fkey" FOREIGN KEY (operator_id) REFERENCES cw_operator5(id)

(END)

The request body of the failiing POST request (update existing row) looks like:失败的POST请求(更新现有行)的请求正文如下所示:

{"id":729,"issue_description":"test","document_number":99,"api_state_code":88,"api_county_code":11,"section":22,"city_id":51,"county_id":56,"operator_id":4415}

Your issue here is that the Complaint model's ID type is UUID , but in your POST request body, you are passing in an Int value.您的问题是Complaint模型的 ID 类型是UUID ,但是在您的POST请求正文中,您传入了一个Int值。 Since you are migrating an existing project that already has a database defined with integer IDs, the best solution for this is to change your model's ID type.由于您正在迁移已具有使用 integer ID 定义的数据库的现有项目,因此最好的解决方案是更改模型的 ID 类型。

Because Fluent 4 attempts to support all databases, by default it only supports UUID ID types.因为 Fluent 4 试图支持所有数据库,所以默认情况下它只支持 UUID ID 类型。 You can have a custom ID type, like this:您可以有一个自定义 ID 类型,如下所示:

@ID(custom: "id", generatedBy: .database) var id: Int?

This will allow your model to work with your current database table structure and take in integer IDs in your POST request body.这将允许您的 model 使用您当前的数据库表结构并在您的POST请求正文中获取 integer ID。

Your model will look like this in the end:您的 model 最终将如下所示:

final class Complaint: Model, Content {

    static let schema = "cw_complaint5"

    @ID(custom: "id", generatedBy: .database)
    var id: Int?

    @Field(key: "issue_description")
    var issue_description: String

    // etc.
    init() { }
}

Solution: serialize the table in PostgreSQL:解决方法:序列化PostgreSQL中的表:

mydb2=# ALTER TABLE cw_complaint5 DROP COLUMN id;

mydb2=# ALTER TABLE cw_complaint5 ADD COLUMN id SERIAL PRIMARY KEY;

Then to insert a row (in xcode 11.4 vapor 4 fluentpostgresql) remove id from your POST request json eg:然后插入一行(在 xcode 11.4 vapor 4 fluentpostgresql 中)从您的 POST 请求 json 中删除 id 例如:

{"section":1,"operator_id":4415 ... etc.}

To update an existing row, include the id in the json.要更新现有行,请在 json 中包含 id。 The following in routes.swift handles both insert and update: routes.swift 中的以下内容同时处理插入和更新:

app.post("complaint") { req -> EventLoopFuture<Complaint> in
    let complaint = try req.content.decode(Complaint.self)
    if let id = complaint.id {
        print("60p \(id)") // Optional(6005)
    }
    return complaint.save(on: req.db)
        .map { complaint }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM