diff --git a/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/EntityCache.kt b/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/EntityCache.kt index 9ad4b73ba0..d4a84a9bc7 100644 --- a/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/EntityCache.kt +++ b/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/EntityCache.kt @@ -14,6 +14,7 @@ val Transaction.entityCache: EntityCache by transactionScope { EntityCache(this) class EntityCache(private val transaction: Transaction) { private var flushingEntities = false private var initializingEntities: LinkedIdentityHashSet> = LinkedIdentityHashSet() + internal val pendingInitializationLambdas = IdentityHashMap, MutableList<(Entity<*>)->Unit>>() val data = LinkedHashMap, MutableMap>>() internal val inserts = LinkedHashMap, MutableSet>>() private val updates = LinkedHashMap, MutableSet>>() @@ -86,6 +87,8 @@ class EntityCache(private val transaction: Transaction) { initializingEntities.remove(entity) } + internal fun isEntityInInitializationState(entity: Entity<*>) = entity in initializingEntities + fun , T : Entity> scheduleInsert(f: EntityClass, o: T) { inserts.getOrPut(f.table) { LinkedIdentityHashSet() }.add(o as Entity<*>) } @@ -199,7 +202,9 @@ class EntityCache(private val transaction: Transaction) { entry.storeWrittenValues() store(entry) transaction.registerChange(entry.klass, entry.id, EntityChangeType.Created) + pendingInitializationLambdas[entry]?.forEach { it(entry) } } + toFlush = partition.second } while (toFlush.isNotEmpty()) } diff --git a/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/InnerTableLink.kt b/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/InnerTableLink.kt index 57b0c02889..eea3b2725d 100644 --- a/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/InnerTableLink.kt +++ b/exposed-dao/src/main/kotlin/org/jetbrains/exposed/dao/InnerTableLink.kt @@ -39,7 +39,7 @@ class InnerTableLink, Source : Entity, ID : Comparabl } override operator fun getValue(o: Source, unused: KProperty<*>): SizedIterable { - if (o.id._value == null) return emptySized() + if (o.id._value == null && !o.isNewEntity()) return emptySized() val sourceRefColumn = getSourceRefColumn(o) val transaction = TransactionManager.currentOrNull() ?: return o.getReferenceFromCache(sourceRefColumn) @@ -59,6 +59,17 @@ class InnerTableLink, Source : Entity, ID : Comparabl } override fun setValue(o: Source, unused: KProperty<*>, value: SizedIterable) { + val entityCache = TransactionManager.current().entityCache + if (entityCache.isEntityInInitializationState(o)) { + entityCache.pendingInitializationLambdas.getOrPut(o) { arrayListOf() }.add { + setReference(it as Source, unused, value) + } + } else { + setReference(o, unused, value) + } + } + + private fun setReference(o: Source, unused: KProperty<*>, value: SizedIterable) { val sourceRefColumn = getSourceRefColumn(o) val tx = TransactionManager.current() diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/entities/ViaTest.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/entities/ViaTest.kt index 6da2b8519e..01301cccf8 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/entities/ViaTest.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/entities/ViaTest.kt @@ -170,11 +170,12 @@ class ViaTests : DatabaseTestsBase() { @Test fun testHierarchicalReferences() { withTables(NodeToNodes) { + addLogger(StdOutSqlLogger) val root = Node.new { name = "root" } val child1 = Node.new { name = "child1" + parents = SizedCollection(root) } - child1.parents = SizedCollection(root) assertEquals(0L, root.parents.count()) assertEquals(1L, root.children.count())