使用Exposed插入带默认值数据时触发非空约束错误
问题原因
你遇到的问题源于Exposed框架中数据库默认值与DAO实体赋值逻辑的冲突:
- 表定义里的
.default(AccountStatus.ACTIVE)是数据库层面的默认值,仅当插入SQL语句完全不包含该字段时,数据库才会自动填充默认值。 - 但使用
User.new创建DAO实体时,所有未显式赋值的字段会被设为null,插入时会生成包含该字段且值为NULL的SQL语句,直接覆盖数据库默认值,触发非空约束错误。
解决方案
以下三种方案可解决问题,按需选择:
方案1:给DAO属性添加Kotlin层面默认值(推荐)
在User实体类中,给accountStatus属性使用Exposed的withDefault委托,确保实体创建时未赋值的情况下自动填充预设值,而非null:
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 // 添加withDefault设置Kotlin层面默认值 override var accountStatus by Users.accountStatus.withDefault { AccountStatus.ACTIVE } val sessions by Session referrersOn Sessions.userId }
调用User.new时即使不指定accountStatus,实体也会自动赋值AccountStatus.ACTIVE,插入SQL会携带正确值,不会触发非空约束。
方案2:改用DSL的insert方法
若无需创建DAO实体,直接使用Exposed DSL插入语句,未指定的字段会自动使用数据库默认值:
transaction { Users.insert { it[email] = email it[role] = role // 无需指定accountStatus,数据库会自动使用默认值 } }
方案3:自定义实体创建方法
在User的companion object中封装创建方法,预设默认值:
class User(id: EntityID<UUID>) : UUIDEntity(id), UserData { companion object : UUIDEntityClass<User>(Users) { // 自定义创建方法,预设accountStatus默认值 fun create(email: String, role: Role): User { return new { this.email = email this.role = role this.accountStatus = AccountStatus.ACTIVE } } } 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 }
调用时直接使用User.create(email, role),避免手动遗漏字段赋值。
内容的提问来源于stack exchange,提问作者TeknoSenpai
相关产品推荐
相关产品推荐

