几天前,我开始使用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
是null。如果我手动添加一个id
-列到模型中,我会收到一个错误,该列已经存在。如果我忽略了在table/2
中将primary_key
设置为false并删除id
列,该表用顺序的id
列生成。
我是否需要在修改器中手动设置id
,或者我在设置应用程序以使用UUID时出错了?
3条答案
按热度按时间amrnrhlw1#
编辑:我已经将这个答案更新到了Ecto v2.0。你可以在最后阅读以前的答案。
体外循环v2
在Ecto中处理UUID比原来的答案要简单得多。Ecto有两种类型的ID:
:id
和:binary_id
。第一种是我们从数据库中知道的整数ID,第二种是数据库特定的二进制。对于Postgres,它是UUID。要将UUID作为主键,请首先在迁移中指定它们:
字符串
然后在模型模块中(
schema
块外部):型
当您为
:binary_id
指定:autogenerate
选项时,Ecto将保证适配器或数据库将为您生成它。但是,如果您愿意,您仍然可以手动生成它。顺便说一句,您可以在迁移中使用:uuid
,在模式中使用Ecto.UUID
而不是:binary_id
,:binary_id
的好处是它可以跨数据库移植。体外循环v1
你需要告诉你的数据库如何自动为你生成UUID。或者你需要从应用程序端生成一个。这取决于你喜欢哪一个。
在我们继续之前,有一点很重要,那就是你使用的
:uuid
将返回二进制文件,而不是人类可读的UUID。很可能你想使用Ecto.UUID
,它将把它格式化为字符串(aaaa-bbb-ccc-...),这就是我下面要使用的。数据库生成
在迁移中,为字段定义默认值:
型
我假设你运行的是PostgreSQL。你需要在pgAdmin中安装uuid-ossp扩展和
CREATE EXTENSION "uuid-ossp"
,或者在迁移中添加execute "CREATE EXTENSION \"uuid-ossp\""
。关于the UUID generator can be found here的更多信息。回到Ecto,在你的模型中,要求Ecto在插入/更新后从数据库中读取字段:
型
现在,当您插入时,数据库将生成一个默认值,Ecto将读回它。
在应用中生成
您需要定义一个模块来插入UUID:
型
并将其用作回调:
型
before_insert
是一个回调函数,它将在给定的函数中调用给定的模块,并将一个表示插入内容的变量作为第一个参数。这应该就是全部了。顺便说一句,将来有可能会更精简。:)
6qfn3psc2#
另外,在创建新项目时,通过选项
--binary-id
使用UUID作为默认主键。(启动Ecto v2)字符串
shyt4zoc3#
在创建新项目的时候,你忘记传递--binary-id选项了吗?没问题!
打开config.exs文件
搜索Ecto,你通常会找到这样的东西:
字符串
只需将--binary-id添加到配置中:
型
当您生成一个新的模式时,它现在将被配置为记住这一点。
就是这样!