ktorm icon indicating copy to clipboard operation
ktorm copied to clipboard

实体类API新增出现异常

Open TxcA opened this issue 1 year ago • 6 comments

  • 数据库PostgreSQL14

  • Gradle:

// https://github.com/pgjdbc/pgjdbc
implementation("org.postgresql:postgresql:42.4.0")

// https://github.com/kotlin-orm/ktorm
// https://www.ktorm.org/zh-cn
implementation("org.ktorm:ktorm-core:3.5.0")
implementation("org.ktorm:ktorm-support-postgresql:3.5.0")

// https://github.com/brettwooldridge/HikariCP
implementation("com.zaxxer:HikariCP:5.0.1")
  • 表结构

CREATE TABLE IF NOT EXISTS public."UserPermission"
(
    -- Inherited from table public."Basic": key text COLLATE pg_catalog."default" NOT NULL DEFAULT uuid_generate_v4(),
    -- Inherited from table public."Basic": create_time timestamp with time zone,
    -- Inherited from table public."Basic": create_user text COLLATE pg_catalog."default",
    -- Inherited from table public."Basic": update_time timestamp with time zone,
    -- Inherited from table public."Basic": update_user text COLLATE pg_catalog."default",
    -- Inherited from table public."Basic": delete_time timestamp with time zone,
    -- Inherited from table public."Basic": delete_user text COLLATE pg_catalog."default",
    -- Inherited from table public."Basic": is_delete boolean,
    id integer NOT NULL DEFAULT nextval('"UserPermission_id_seq"'::regclass),
    user_key text COLLATE pg_catalog."default",
    tag text COLLATE pg_catalog."default",
    permission text COLLATE pg_catalog."default",
    CONSTRAINT "UserPermission_pkey" PRIMARY KEY (id)
)

实体定义:

val Database.userPermission get() = this.sequenceOf(TableUserPermission)

object TableUserPermission : ITable<UserPermission>("UserPermission") {
    val id = int("id").primaryKey().bindTo { it.id }
    val userKey = text("user_key").bindTo { it.userKey }
    val tag = text("tag").bindTo { it.tag }
    val permission = int("permission").bindTo { it.permission }
}

interface UserPermission : IEntity<UserPermission> {
    companion object : Entity.Factory<UserPermission>()

    var id: Int
    var userKey: String
    var tag: String
    var permission: Int
}

调用代码:

database.userPermission.add(UserPermission {
    this.createTime = LocalDateTime.now()
    this.createUser = "X"

    this.userKey = "userKey"
    this.tag = "SD"
    this.permission = 31
})
  • 问题描述: 我检查了字段类型和数据,发现数据是已经成功插入了的。 检查数据,发现异常中的 d6e86908-a1be-483d-8ba5-edbd24e07029 为表内key字段自动生成的uuid_generate_v4(),并不是我传入的数据。

  • 异常堆栈:

java.lang.NumberFormatException: For input string: "d6e86908-a1be-483d-8ba5-edbd24e07029"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
	at java.base/java.lang.Integer.parseInt(Integer.java:668)
	at java.base/java.lang.Integer.parseInt(Integer.java:786)
	at org.ktorm.database.CachedRowSet.getInt(CachedRowSet.kt:357)
	at org.ktorm.schema.IntSqlType.doGetResult(SqlTypes.kt:68)
	at org.ktorm.schema.IntSqlType.doGetResult(SqlTypes.kt:61)
	at org.ktorm.schema.SqlType.getResult(SqlType.kt:59)
	at org.ktorm.entity.EntityDmlKt.add(EntityDml.kt:74)
	at -.db.table.DBUserPermission.addOrUpdateUserPermission(TableUserPermission.kt:110)
	at -.api.ManageX$link$1$1.invokeSuspend(ManageX.kt:59)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:503)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:995)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda-1$lambda-0(NettyApplicationEngine.kt:260)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)

切换为以下方法可以调用成功:

database.insert(TableUserPermission) {
    set(it.createTime, LocalDateTime.now())
    set(it.createUser, "X")
    set(it.userKey, "userKey")
    set(it.tag, "SD")
    set(it.permission, 31)
}

TxcA avatar Jul 08 '22 01:07 TxcA

为什么你的表会自动生成 uuid 呢,生成 uuid 的字段名是什么

vincentlauvlwj avatar Jul 08 '22 04:07 vincentlauvlwj

刚代码没截全,由于我这边表有很多的公用字段,所以封装了ITableIEntity。 上面的代码可以看到,我的UserPermission是继承IEntityITable的。

uuid 是使用 PostgreSql的 uuid_generate_v4()自动生成的 ,数据库里绑定的是key 这个字段。

  • ITable
open class ITable<E : IEntity<E>>(
    tableName: String,
    alias: String? = null,
    catalog: String? = null,
    schema: String? = null,
    entityClass: KClass<E>? = null
) : Table<E>(tableName, alias, catalog, schema, entityClass) {
    val key = text("key").bindTo { it.key }
    val createTime = datetime("create_time").bindTo { it.createTime }
    val createUser = text("create_user").bindTo { it.createUser }
    val updateTime = datetime("update_time").bindTo { it.updateTime }
    val updateUser = text("update_user").bindTo { it.updateUser }
    val deleteTime = datetime("delete_time").bindTo { it.deleteTime }
    val deleteUser = text("delete_user").bindTo { it.deleteUser }
    val isDelete = boolean("is_delete").bindTo { it.isDelete }
}
  • IEntity
interface IEntity<E : Entity<E>> : Entity<E>{
    val key: String
    var createTime: LocalDateTime
    var createUser: String
    var updateTime: LocalDateTime?
    var updateUser: String?
    var deleteTime: LocalDateTime?
    var deleteUser: String?
    var isDelete: Boolean
}

TxcA avatar Jul 08 '22 04:07 TxcA

你的表里面有两个自动生成的字段(id & key),这会导致 ktorm 在 insert 成功之后获取主键出问题,因为 ktorm 假设生成的主键只有一个,后面我们想办法看看怎么修复

vincentlauvlwj avatar Jul 08 '22 09:07 vincentlauvlwj

好的谢谢。

TxcA avatar Jul 08 '22 09:07 TxcA

感谢你的反馈,如果可能的话,你把 key 字段的 DEFAULT uuid_generate_v4() 去掉,应该可以暂时避免这个问题

vincentlauvlwj avatar Jul 08 '22 09:07 vincentlauvlwj

谢谢,目前可以先用database.insert(TableUserPermission) {...}

TxcA avatar Jul 11 '22 00:07 TxcA