在 MariaDB 中保存 UUID 以用于 Vapor
Posted
技术标签:
【中文标题】在 MariaDB 中保存 UUID 以用于 Vapor【英文标题】:saving an UUID in MariaDB for use with Vapor 【发布时间】:2020-01-05 16:01:22 【问题描述】:我想在 Vapor 中使用 Fluentmysql 来保存数据,但我无法正确读取 UUID。
如果我使用 MariaDB 提供的 UUID() 函数,一切都很好,但如果我使用 FluentMySQL,则 UUID 被打乱: (第一条记录:UUID() 的用法,第二条记录:Vapor)
MariaDB [someDB]> select * from Poll;
+--------------------------------------+-------+---------+---------+--------+--------+
| id | title | option1 | option2 | votes1 | votes2 |
+--------------------------------------+-------+---------+---------+--------+--------+
| 88a18a58-2fcd-11ea-9f62-e283e8014c79 | test | bla | bla | 0 | 0 |
| 7??/.?E??*_P?v | bla | option1 | option2 | 1 | 2 |
+--------------------------------------+-------+---------+---------+--------+--------+
2 rows in set (0.00 sec)
这是我的模型:
import Foundation
import FluentMySQL
import Vapor
struct Poll: Content, MySQLUUIDModel, Migration
typealias ID = UUID
static let entity: String = "Poll"
var id: UUID?
var title: String
var option1: String
var option2: String
var votes1: Int
var votes2: Int
这是我的桌子:
MariaDB [someDB]> describe Poll;
+---------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id | varchar(191) | YES | | NULL | |
| title | varchar(191) | YES | | NULL | |
| option1 | varchar(191) | YES | | NULL | |
| option2 | varchar(191) | YES | | NULL | |
| votes1 | int(10) | YES | | NULL | |
| votes2 | int(10) | YES | | NULL | |
+---------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
但是如果使用 Vapor 来获取数据,一切似乎都很好。我做错了什么?
通过 curl 输出:
curl http://locurl http://localhost:8080/polls/list
["option1":"bla","id":"38386131-3861-3538-2D32-6663642D3131","title":"test","option2":"bla","votes1":0,"votes2":0,"option1":"option1","id":"373F3F2F-2E3F-453F-3F0E-2A5F503F7607","title":"bla","option2":"option2","votes1":1,"votes2":2]
感谢您提前提供帮助。
【问题讨论】:
所以,我创建了一个新条目。生成的 UUID 为“5ECDB258-7B5B-4A80-A7B7-DFA2C6D33ED5”,但显示为“^ͲX[J??????>?”在mariadb。也许有人知道出了什么问题? (我猜是某种类型不匹配) 看起来一个有十六进制版本,一个有二进制版本。 【参考方案1】:如果您使用 Vapor 自己创建一个 UUID
字段,它会创建一个数据类型为 varbinary(16)
而不是 varchar(191)
的字段。这与 MariaDB/MySQL 中 UUID 字段的默认格式一致。
我认为这是一个遗留应用程序,数据是在 Vapor 之外创建的?看起来您正在存储 UUID 值的字符串表示形式,而不是底层二进制值。如果您假设这些值都是可打印的,那么将二进制值存储在 varchar
字段中只会导致问题(正如您所发现的)。但是,在同一列中混合使用字符串和二进制格式的值很可能会导致问题。
【讨论】:
不,这不是遗留应用程序 - 这是我第一次尝试编写后端代码(我有 ios 开发背景)。 UUID 通常由 Vapor 生成,但我认为两者都应该是可能的:在 Vapor 之外和由 Vapor 生成。我将类型从 varchar(191) 更改为 varbinary(16)。输出仍然“混乱”,但如果我使用 hex(),MariaDB 会显示 UUID,但它缺少破折号。感谢您指出类型错误。如果从数据库中获取值,通常需要转换吗? 我现在找到了解决方案:正如尼克指出的,类型必须是 varbinary(16)。如果一个人使用 MySQL,他/她可以使用 bin_to_uuid 但 MariaDB 用户需要执行 SELECT upper(CONCAT( SUBSTR(HEX(id), 1, 8), '-', SUBSTR(HEX(id), 9, 4), '-', SUBSTR(HEX(id), 13, 4), '-', SUBSTR(HEX(id), 17, 4), '-', SUBSTR(HEX(id), 21) )) FROM Poll;但是这个功能很快就会在 MariaDB 中实现。以上是关于在 MariaDB 中保存 UUID 以用于 Vapor的主要内容,如果未能解决你的问题,请参考以下文章
[mysql] MariaDB 10.0.10 GTID复制
使用 Laravel 关系 orm 时 UUID 二进制(16)的问题
在 MariaDB 中,放置在触发器中的函数开始返回不同的值
使用 Play Slick 在 PostgreSQL 中持久化 UUID - java.sql.BatchUpdateException