gpt4 book ai didi

postgresql - 设置 Phoenix Framework 和 Ecto 以使用 UUID : how to insert the generated value?

转载 作者:行者123 更新时间:2023-11-29 11:09:07 26 4
gpt4 key购买 nike

几天前,我开始将 Elixir 和 Phoenix Framework (v 0.12.0) 与 Postgres 数据库一起使用。我正在尝试创建一个具有 UUID 主键的表,我更喜欢顺序默认值。

在使用mix phoenix.gen.html 生成模型和迁移文件并遵循 Phoenix 文档中的其他步骤后,我进行了更改

def model do
quote do
use Ecto.Model
end
end

web.ex

def model do
quote do
use Ecto.Model
@primary_key {:id, :uuid, []}
@foreign_key_type :uuid
end
end

如 Ecto 文档中所述。我还将迁移更改为

create table(:tblname, primary_key: false) do
add :id, :uuid, primary_key: true
[other columns]
end

不幸的是,当我尝试从自动生成的表单向表中添加条目时,我收到错误消息,因为 id 为空。如果我手动将 id 列添加到模型中,我会收到一条错误消息,指出该列已存在。如果我忽略在 table/2 中将 primary_key 设置为 false 并删除 id 列,则生成的表具有顺序 id -列。

我是否需要在变更集中手动设置 id,或者我在将我的应用设置为使用 UUID 时犯了错误?提前致谢

最佳答案

编辑:我已将此答案更新为 Ecto v2.0。您可以在最后阅读之前的答案。

外链v2

自最初的答案以来,在 Ecto 中处理 UUID 变得更加直接。 Ecto 有两种类型的 ID::id:binary_id。第一个是我们从数据库中知道的整数 ID,第二个是特定于数据库的二进制文件。对于 Postgres,它是一个 UUID。

要将 UUID 作为主键,首先在迁移中指定它们:

create table(:posts, primary_key: false) do
add :id, :binary_id, primary_key: true
end

然后在您的模型模块中(在 schema block 之外):

@primary_key {:id, :binary_id, autogenerate: true}

当您为:binary_id 指定:autogenerate 选项时,Ecto 将保证适配器或数据库会为您生成它。但是,如果您愿意,您仍然可以手动生成它。顺便说一句,您可以在迁移中使用 :uuid 并在架构中使用 Ecto.UUID 而不是 :binary_id,这是 的好处:binary_id 是它可以跨数据库移植。

外链 v1

您需要告诉您的数据库如何自动为您生成 UUID。或者您需要从应用程序端生成一个。这取决于您喜欢哪一个。

在我们继续之前,重要的是要说明您正在使用 :uuid ,它将返回二进制文件而不是人类可读的 UUID。您很可能想使用 Ecto.UUID,它将其格式化为字符串 (aaaa-bbb-ccc-...),这就是我将在下面使用的内容。

在数据库中生成

在您的迁移中,为该字段定义一个默认值:

add :id, :uuid, primary_key: true, default: fragment("uuid_generate_v4()")

我假设您在 PostgreSQL 上运行。您需要在 pgAdmin 中使用 CREATE EXTENSION "uuid-ossp" 安装 uuid-ossp 扩展,或者在迁移中添加 execute "CREATE EXTENSION\"uuid-ossp\"" .有关 the UUID generator can be found here 的更多信息.

回到 Ecto,在你的模型中,要求 Ecto 在插入/更新后从数据库中读取字段:

@primary_key {:id, Ecto.UUID, read_after_writes: true}

现在,当你插入时,数据库会生成一个默认值,Ecto 会读回它。

在应用程序中生成

您需要定义一个为您插入 UUID 的模块:

defmodule MyApp.UUID do
def put_uuid(changeset) do
Ecto.Changeset.put_change(changeset, :id, Ecto.UUID.generate())
end
end

并将其用作回调:

def model do
quote do
use Ecto.Model
@primary_key {:id, Ecto.UUID, []}
@foreign_key_type Ecto.UUID
before_insert MyApp.UUID, :put_uuid, []
end
end

before_insert 是一个回调函数,它将使用给定的参数在给定的函数中调用给定的模块,其中一个代表正在插入的内容的变更集作为第一个参数给出。

应该就这些了。顺便说一句,将来这可能会更加精简。 :)

关于postgresql - 设置 Phoenix Framework 和 Ecto 以使用 UUID : how to insert the generated value?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30004008/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com