在Exposed DAO的做法中扩展多对多关系时,如果已经分配了某些无关的对象,就会失败
我正在学习使用DAO方式的Kotlin Exposed。我正在为 Employee 与 Department之间建立多对多关系。接着我尝试建立连接:
transaction {
SchemaUtils.create(EmployeeTable, DepartmentTable, EmployeeInDepartmentTable)
val amy = Employee.new {
name = "Amy"
}
val nick = Employee.new {
name = "Nick"
}
val sales = Department.new {
name = "Sales"
}
nick.departments = SizedCollection(nick.departments + sales)
amy.departments = SizedCollection(amy.departments + sales)
}
这段代码工作正常,能够正确把 nick 和 amy 与 sales 连接起来。
然而,当我尝试用一个员工初始化 sales,然后再添加一个新的时,就会出现问题:
transaction {
SchemaUtils.create(EmployeeTable, DepartmentTable, EmployeeInDepartmentTable)
val amy = Employee.new {
name = "Amy"
}
val nick = Employee.new {
name = "Nick"
}
val sales = Department.new {
name = "Sales"
employees = SizedCollection(amy) // adding amy in intialization
}
nick.departments = SizedCollection(nick.departments + sales)
}
在尝试修改 nick.departments 时会抛出 IllegalStateException: Entity must be inserted。
更有趣的是,如果把 nick.departments = SizedCollection(nick.departments + sales) 替换为 nick.departments = SizedCollection(sales)(也就是说,我们根本不去查询Nick的空集合),这次就成功了:
transaction {
SchemaUtils.create(EmployeeTable, DepartmentTable, EmployeeInDepartmentTable)
val amy = Employee.new {
name = "Amy"
}
val nick = Employee.new {
name = "Nick"
}
val sales = Department.new {
name = "Sales"
employees = SizedCollection(amy) // adding amy in intialization
}
nick.departments = SizedCollection(sales) // works, really...
}
这是为什么呢?
我正在使用以下工具和配置:
[versions]
kotlin = "2.4.0"
exposed = "1.3.0"
h2 = "2.4.240"
[libraries]
exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" }
h2 = { module = "com.h2database:h2", version.ref = "h2" }
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
以及以下数据库连接:
Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
以及以下的DAOs:
object DepartmentTable : IntIdTable() {
val name = varchar("nam", 50)
}
class Department(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Department>(DepartmentTable)
var name by DepartmentTable.name
var employees by Employee via EmployeeInDepartmentTable
}
object EmployeeTable : IntIdTable() {
val name = varchar("nam", 50)
}
class Employee(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Employee>(EmployeeTable)
var name by EmployeeTable.name
var departments by Department via EmployeeInDepartmentTable
}
object EmployeeInDepartmentTable : Table() {
val employee = reference("student", EmployeeTable)
val department = reference("group", DepartmentTable)
override val primaryKey = PrimaryKey(employee, department)
}
解决方案
你最初把Nick设置为销售部
并且你最后一行写道
...Nick.Depts + Sales ...那就是Sales + Sales
你应该不能把他在Sales中重复添加 = 出错!
如果在Depts中设置Ref.Integrity(无重复项:)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。