Kotlin Exposed 使用引用创建实体
Posted
技术标签:
【中文标题】Kotlin Exposed 使用引用创建实体【英文标题】:Kotlin Exposed create entity with reference 【发布时间】:2021-05-12 12:23:05 【问题描述】:我正在尝试在 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
)
这里是创建的服务方法
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]
保存实体后调用toContact()方法报错
var contact = contactEntity.toContact()
创建此类实体的正确方法是什么?
【问题讨论】:
【参考方案1】:您需要在 create 方法的事务中调用 toContact 方法。
记录的嵌套用户记录只能从事务内部懒惰地访问。
我通过让任何数据访问层接口使用我自己的数据类来解决这个问题。暴露的记录和表在该层下保持私有。不要让事务实体在其上方泄漏。
下面的例子用一个嵌套的用户来说明:
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()
编辑:另一种方法是不使用引用的用户记录,而是将其保留为用户 ID?但可能您在其他查询中需要此嵌套记录。
【讨论】:
以上是关于Kotlin Exposed 使用引用创建实体的主要内容,如果未能解决你的问题,请参考以下文章
如何避免Kotlin暴露的N + 1查询问题。 (通过DAO的Reference.id.value字段获取值时)
如何通过 Exposed 连接到 Google Cloud SQL