AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79527176
Accepted
TeknoSenpai
TeknoSenpai
Asked: 2025-03-22 17:08:20 +0800 CST2025-03-22 17:08:20 +0800 CST 2025-03-22 17:08:20 +0800 CST

在 Exposed 中插入默认值时出错

  • 772

每当我尝试在 Users 表中创建并插入新用户时(使用User.newDAO 方法或Users.insert方法),具有默认值且被描述为非空的枚举字段 accountstatus 会导致插入失败null value in column "accountstatus" violates not-null constraint。

以下是表定义和用户 DAO 的代码:

 object Users : UUIDTable() {
     val email = varchar("email", 255).uniqueIndex()
     val role = enumeration<Role>("role")
     val registrationDate =
         datetime("registrationDate").default(Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()))
     val disabledDate = datetime("disabledDate").nullable()
     val accountStatus = enumeration<AccountStatus>("accountStatus").default(AccountStatus.ACTIVE)
 
     enum class Role {
         PROFESSOR, STUDENT
     }
 
     enum class AccountStatus {
         ACTIVE, DISABLED
     }
 }

 class User(id: EntityID<UUID>) : UUIDEntity(id), UserData {
     companion object : UUIDEntityClass<User>(Users)
 
     override var email by Users.email
     override var role by Users.role
     override val registrationDate by Users.registrationDate
     override var disabledDate by Users.disabledDate
     override var accountStatus by Users.accountStatus
     val sessions by Session referrersOn Sessions.userId
 }

以下是引发异常的代码:

 // ...
 transaction {
     User.new {
         email = email /* logic omitted */
         role = role /* logic omitted */
     }
 }
database
  • 1 1 个回答
  • 35 Views

1 个回答

  • Voted
  1. Best Answer
    Lajos Arpad
    2025-03-22T18:03:02+08:002025-03-22T18:03:02+08:00

    该问题已在GitHub上讨论过。

    问题

    对于插入,Exposed 将(对于没有明确值的列)使用来自 Exposed 表对象中的默认值/空值填充所有插入,而不是通过在插入语句中省略该列来实际使用数据库上的实际表中定义的插入。

    这有几个问题:

    使用数据库默认值实际上不可能执行 INSERT。也就是说,它可能不被其他团队所知或控制。归根结底,这需要保持代码与数据库同步,但这与始终在线的服务相矛盾,因为根据定义,始终在线的服务必须同时在数据库上运行新代码和旧代码。

    一个更加灵活和更少主观的设计将涉及:

    仅使用 .default() 和 .defaultExpression() 来创建表。同时使用 .clientDefault()(和 .default()),然后将其作为应用程序默认值(我一直认为它是这样工作的),而不是让 .default() 同时充当表和客户端插入默认值。对于可空列,不要隐式地将默认值设为 NULL。这是第一点的要求。

    需要注意的是,我并不是在谈论 Exposed Dao,而是普通查询 dsl。查看 git 历史记录,似乎这些默认值是作为 dao 的默认默认值引入的,我想这更有意义(除了它们仍然无法选择退出)。但它们溢出到了 dsl 中,我发现这很成问题,因为 dsl 应该支持所有(或至少是标准)sql。我假设当前行为可以向上移动到 dao 代码的一层,以保持 dao 的行为完整。

    我可能愿意做与此相关的大部分工作,但想确认这是否可取。

    类似问题 #345

    回答

    如果我理解正确的话,问题似乎已经解决了。

    如果问题在于 Exposed 强烈要求为所有字段定义值,并且不允许依赖数据库端值生成,则可以使用列方法 databaseGenerated() (以及 withDefinition() )来解决

    其实,目前有3种方法(以PostgresDB为例):

    default()/defaultExpression() (自定义列 DDL,并应用于插入语句)

    object TestTable : IntIdTable("test") {
        val key = uuid("key")
            .default(UUID.fromString("a344698c-3c0d-46a7-9847-dc308665d9c8"))
    }
    
    TestTable.insert {  }
    

    执行的sql:

    CREATE TABLE IF NOT EXISTS test (
      id SERIAL PRIMARY KEY, 
      "key" uuid DEFAULT 'a344698c-3c0d-46a7-9847-dc308665d9c8' NOT NULL
    )
    
    INSERT INTO test ("key") VALUES ('a344698c-3c0d-46a7-9847-dc308665d9c8')
    

    clientDefault()(不影响 DDL):

    object TestTable : IntIdTable("test") {
      val key = uuid("key")
          .clientDefault { UUID.randomUUID() }
    }
    
    TestTable.insert {  }
    
    CREATE TABLE IF NOT EXISTS test (
      id SERIAL PRIMARY KEY, 
      "key" uuid NOT NULL
    )
    
    INSERT INTO test ("key") VALUES ('e69515f6-6bed-4c95-aa75-9c0ba7a0ac77')
    

    databaseGenerated().withDefinition() (此变体修改表列,插入时跳过该值)

    object TestTable : IntIdTable("test") {
        val key = uuid("key")
            .databaseGenerated()
            .withDefinition("DEFAULT gen_random_uuid()")
    }
    
    TestTable.insert {  }
    
    CREATE TABLE IF NOT EXISTS test (
      id SERIAL PRIMARY KEY, 
      "key" uuid DEFAULT gen_random_uuid() NOT NULL
    )
    
    INSERT INTO test  DEFAULT VALUES
    

    查看这些变体,用户可能会感到困惑,因为存在客户端生成、数据库端生成和适用于两者的魔术 default() 的变体。

    可能我们实际上并不需要 default() 变体,因为它定制了 DDL 来在数据库端生成值,但之后无论如何都会将相同的值放入查询中。

    可能最好只有两个选项(客户端或数据库端生成)和一致的方法设置,例如:

    • 客户端生成(值)
    • clientGeneratedByExpression(表达式:)
    • 数据库生成()
    • databaseGeneratedByDefinition(定义)

    我认为这里最有趣的问题是:是否存在 default() 不能被 clientDefault() / databaseGenerated() 选项替换的用例?如果没有这样的用例,我们至少可以将 default() 标记为已弃用。@e5l @bog-walk 你怎么看?

    无论如何,这只是一些关于如何使其更加一致的建议。根据问题的初始问题,在我看来问题已经解决,如果没有,请告诉我。

    概括

    databaseGenerated().withDefinition()似乎就是您正在寻找的东西。

    • 1

相关问题

  • 从交互式数据包装器地图收集数据

  • 尝试创建触发器时 Oracle 出错

  • 如何正确创建mongo模型和客户端?

  • 如何在同一个表的派生部分引用主键?

  • 仅允许通过 powerapps 访问我的 Microsoft 列表或 Onedrive 中的 Excel

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve