Kotlin Excessed 通过引用创建实体

Ale*_*dar 2 kotlin kotlin-exposed

我正在尝试使用 Kotlin 上的 Exposed 编写 CRUD 服务。我有一张包含多对一参考的表格。当我尝试插入时,我得到了

java.lang.IllegalStateException:上下文中没有事务。

这是表和实体

object Contacts : IntIdTable("ph_contact"){
    var firstName = varchar("first_name",255)
    var lastName = varchar("last_name",255)
    var phone = varchar("phone",4096)
    var email = varchar("email",4096)
    var user = reference("user",Users)
}

class ContactEntity (id: EntityID<Int>): IntEntity(id){
    companion object : IntEntityClass<ContactEntity>(Contacts)

    var firstName by Contacts.firstName
    var lastName by Contacts.lastName
    var phone by Contacts.phone
    var email by Contacts.email
    var user by UserEntity referencedOn Contacts.user


    fun toContact() = Contact(id.value,user.id.value,firstName,lastName,phone,email)

}


data class Contact(
    val id: Int,
    val userId: Int,
    val firstName: String,
    val lastName: String,
    val phone: String,
    val email: String
)
Run Code Online (Sandbox Code Playgroud)

这是创建的服务方法

fun createContact(contact: Contact) = transaction {

        ContactEntity.new {

           this.firstName=contact.firstName
           this.lastName=contact.lastName
           this.phone=contact.phone
           this.email=contact.email
           this.user= UserEntity[contact.userId]

        }
    }
Run Code Online (Sandbox Code Playgroud)

保存实体后调用 toContact() 方法时抛出错误

var contact = contactEntity.toContact()

创建此类实体的正确方法是什么?

Lau*_*nce 6

您需要在 create 方法的事务中调用 toContact 方法。

记录的嵌套用户记录只能从事务内部延迟访问。

我通过使任何数据访问层接口使用我自己的数据类来解决这个问题。暴露的记录和表在该层之下保持私有。不要让事务实体在其上方泄漏。

下面以嵌套 User 为例进行说明:

object Users : IntIdTable("ph_users") {
    var otherUserData = varchar("other_user_data", 255)
}

class UserEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<UserEntity>(Users)

    var otherUserData by Users.otherUserData


    fun toUser() = User(id.value, otherUserData)

}

object Contacts : IntIdTable("ph_contact") {
    var firstName = varchar("first_name", 255)
    var lastName = varchar("last_name", 255)
    var phone = varchar("phone", 4096)
    var email = varchar("email", 4096)
    var user = reference("user", Users)
}

class ContactEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<ContactEntity>(Contacts)

    var firstName by Contacts.firstName
    var lastName by Contacts.lastName
    var phone by Contacts.phone
    var email by Contacts.email
    var user by UserEntity referencedOn Contacts.user

    fun toContact() = Contact(id.value, user.toUser(), firstName, lastName, phone, email)
}


data class Contact(
    val id: Int,
    val user: User,
    val firstName: String,
    val lastName: String,
    val phone: String,
    val email: String
)

data class User(
    val id: Int,
    val otherUserData: String
)

class ContactsRepo {

    fun createContact(contact: Contact): Contact = transaction {
        ContactEntity.new {
            this.firstName = contact.firstName
            this.lastName = contact.lastName
            this.phone = contact.phone
            this.email = contact.email
            this.user = UserEntity[contact.user.id]

        }.toContact()
    }

}
Run Code Online (Sandbox Code Playgroud)

编辑:另一种方法是不让用户记录引用,而只是将其保留为用户 ID?但您可能在其他查询中需要此嵌套记录。