diff --git a/repos/exposed/build.gradle b/repos/exposed/build.gradle
index a9382eaa414..dcb01813d04 100644
--- a/repos/exposed/build.gradle
+++ b/repos/exposed/build.gradle
@@ -9,6 +9,7 @@ kotlin {
     sourceSets {
         commonMain {
             dependencies {
+                api internalProject("micro_utils.coroutines")
                 api internalProject("micro_utils.repos.common")
                 api internalProject("micro_utils.pagination.exposed")
             }
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ColumnAllocator.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ColumnAllocator.kt
new file mode 100644
index 00000000000..74bebd14606
--- /dev/null
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ColumnAllocator.kt
@@ -0,0 +1,6 @@
+package dev.inmo.micro_utils.repos.exposed
+
+import org.jetbrains.exposed.sql.Column
+import org.jetbrains.exposed.sql.Table
+
+typealias ColumnAllocator<T> = Table.() -> Column<T>
\ No newline at end of file
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedCRUDRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedCRUDRepo.kt
index 774264f44db..4ef53f226b0 100644
--- a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedCRUDRepo.kt
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedCRUDRepo.kt
@@ -3,9 +3,7 @@ package dev.inmo.micro_utils.repos.exposed
 import dev.inmo.micro_utils.repos.Repo
 import org.jetbrains.exposed.sql.*
 
-interface ExposedCRUDRepo<ObjectType, IdType> : Repo {
-    val database: Database
-
+interface ExposedCRUDRepo<ObjectType, IdType> : ExposedRepo {
     val ResultRow.asObject: ObjectType
     val selectById: SqlExpressionBuilder.(IdType) -> Op<Boolean>
 }
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedRepo.kt
new file mode 100644
index 00000000000..a31d5d0f82e
--- /dev/null
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedRepo.kt
@@ -0,0 +1,10 @@
+package dev.inmo.micro_utils.repos.exposed
+
+import dev.inmo.micro_utils.repos.Repo
+import org.jetbrains.exposed.sql.Database
+
+interface ExposedRepo : Repo {
+    val database: Database
+
+    fun onInit()
+}
\ No newline at end of file
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedTableInitialization.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedTableInitialization.kt
index 6f23d0dbb80..8b0587c96b2 100644
--- a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedTableInitialization.kt
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/ExposedTableInitialization.kt
@@ -6,3 +6,5 @@ import org.jetbrains.exposed.sql.transactions.transaction
 fun Table.initTable(database: Database) {
     transaction(database) { SchemaUtils.createMissingTablesAndColumns(this@initTable) }
 }
+
+fun <T> T.initTable() where T: ExposedRepo, T: Table = initTable(database)
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/AbstractExposedKeyValueRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/ExposedKeyValueRepo.kt
similarity index 70%
rename from repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/AbstractExposedKeyValueRepo.kt
rename to repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/ExposedKeyValueRepo.kt
index f4e53f0997d..f013ae86232 100644
--- a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/AbstractExposedKeyValueRepo.kt
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/ExposedKeyValueRepo.kt
@@ -1,6 +1,7 @@
 package dev.inmo.micro_utils.repos.exposed.keyvalue
 
 import dev.inmo.micro_utils.repos.StandardKeyValueRepo
+import dev.inmo.micro_utils.repos.exposed.*
 import kotlinx.coroutines.channels.BroadcastChannel
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.flow.Flow
@@ -8,14 +9,14 @@ import kotlinx.coroutines.flow.asFlow
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.transactions.transaction
 
-abstract class AbstractExposedKeyValueRepo<Key, Value>(
+open class ExposedKeyValueRepo<Key, Value>(
     database: Database,
-    keyColumn: Column<Key>,
-    valueColumn: Column<Value>
-) : StandardKeyValueRepo<Key, Value>, AbstractExposedReadKeyValueRepo<Key, Value>(
+    keyColumnAllocator: ColumnAllocator<Key>,
+    valueColumnAllocator: ColumnAllocator<Value>
+) : StandardKeyValueRepo<Key, Value>, ExposedRepo, ExposedReadKeyValueRepo<Key, Value>(
     database,
-    keyColumn,
-    valueColumn
+    keyColumnAllocator,
+    valueColumnAllocator
 ) {
     private val onNewValueChannel = BroadcastChannel<Pair<Key, Value>>(Channel.BUFFERED)
     private val onValueRemovedChannel = BroadcastChannel<Key>(Channel.BUFFERED)
@@ -23,6 +24,8 @@ abstract class AbstractExposedKeyValueRepo<Key, Value>(
     override val onNewValue: Flow<Pair<Key, Value>> = onNewValueChannel.asFlow()
     override val onValueRemoved: Flow<Key> = onValueRemovedChannel.asFlow()
 
+    override fun onInit() { initTable() }
+
     override suspend fun set(k: Key, v: Value) {
         transaction(database) {
             if (select { keyColumn.eq(k) }.limit(1).any()) {
@@ -46,3 +49,6 @@ abstract class AbstractExposedKeyValueRepo<Key, Value>(
         onValueRemovedChannel.send(k)
     }
 }
+
+@Deprecated("Renamed", ReplaceWith("ExposedKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo"))
+typealias AbstractExposedKeyValueRepo<Key, Value> = ExposedKeyValueRepo<Key, Value>
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/AbstractExposedReadKeyValueRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/ExposedReadKeyValueRepo.kt
similarity index 66%
rename from repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/AbstractExposedReadKeyValueRepo.kt
rename to repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/ExposedReadKeyValueRepo.kt
index 867f7439cd8..f91efecdc5e 100644
--- a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/AbstractExposedReadKeyValueRepo.kt
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/keyvalue/ExposedReadKeyValueRepo.kt
@@ -2,16 +2,21 @@ package dev.inmo.micro_utils.repos.exposed.keyvalue
 
 import dev.inmo.micro_utils.pagination.*
 import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
+import dev.inmo.micro_utils.repos.exposed.*
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.transactions.transaction
 
-abstract class AbstractExposedReadKeyValueRepo<Key, Value>(
-    protected val database: Database,
-    protected val keyColumn: Column<Key>,
-    protected val valueColumn: Column<Value>
-) : ReadStandardKeyValueRepo<Key, Value>, Table() {
+open class ExposedReadKeyValueRepo<Key, Value>(
+    override val database: Database,
+    keyColumnAllocator: ColumnAllocator<Key>,
+    valueColumnAllocator: ColumnAllocator<Value>,
+) : ReadStandardKeyValueRepo<Key, Value>, ExposedRepo, Table() {
+    protected val keyColumn: Column<Key> = keyColumnAllocator()
+    protected val valueColumn: Column<Value> = valueColumnAllocator()
     override val primaryKey: PrimaryKey = PrimaryKey(keyColumn, valueColumn)
 
+    override fun onInit() { initTable() }
+
     override suspend fun get(k: Key): Value? = transaction(database) {
         select { keyColumn.eq(k) }.limit(1).firstOrNull() ?.getOrNull(valueColumn)
     }
@@ -34,3 +39,6 @@ abstract class AbstractExposedReadKeyValueRepo<Key, Value>(
         }
     }.createPaginationResult(pagination, count())
 }
+
+@Deprecated("Renamed", ReplaceWith("ExposedReadKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedReadKeyValueRepo"))
+typealias AbstractExposedReadKeyValueRepo<Key, Value> = ExposedReadKeyValueRepo<Key, Value>
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/AbstractExposedOneToManyKeyValueRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/AbstractExposedOneToManyKeyValueRepo.kt
deleted file mode 100644
index f0f5e45aa1e..00000000000
--- a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/AbstractExposedOneToManyKeyValueRepo.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package dev.inmo.micro_utils.repos.exposed.onetomany
-
-import dev.inmo.micro_utils.repos.OneToManyKeyValueRepo
-import org.jetbrains.exposed.sql.*
-import org.jetbrains.exposed.sql.transactions.transaction
-
-abstract class AbstractExposedOneToManyKeyValueRepo<Key, Value>(
-    keyColumnAllocator: ColumnAllocator<Key>,
-    valueColumnAllocator: ColumnAllocator<Value>,
-    database: Database
-) : OneToManyKeyValueRepo<Key, Value>, AbstractExposedReadOneToManyKeyValueRepo<Key, Value>(
-    keyColumnAllocator,
-    valueColumnAllocator,
-    database
-) {
-    override suspend fun add(k: Key, v: Value) {
-        transaction(database) {
-            insert {
-                it[keyColumn] = k
-                it[valueColumn] = v
-            }
-        }
-    }
-
-    override suspend fun remove(k: Key, v: Value) {
-        transaction(database) { deleteWhere { keyColumn.eq(k).and(valueColumn.eq(v)) } }
-    }
-
-    override suspend fun clear(k: Key) {
-        transaction(database) { deleteWhere { keyColumn.eq(k) } }
-    }
-}
-
-@Deprecated("Renamed", ReplaceWith("AbstractExposedOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.onetomany.AbstractExposedOneToManyKeyValueRepo"))
-typealias AbstractOneToManyExposedKeyValueRepo<Key, Value> = AbstractExposedOneToManyKeyValueRepo<Key, Value>
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/ExposedOneToManyKeyValueRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/ExposedOneToManyKeyValueRepo.kt
new file mode 100644
index 00000000000..d8202db1ad2
--- /dev/null
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/ExposedOneToManyKeyValueRepo.kt
@@ -0,0 +1,58 @@
+package dev.inmo.micro_utils.repos.exposed.onetomany
+
+import dev.inmo.micro_utils.coroutines.BroadcastFlow
+import dev.inmo.micro_utils.repos.OneToManyKeyValueRepo
+import dev.inmo.micro_utils.repos.exposed.ColumnAllocator
+import dev.inmo.micro_utils.repos.exposed.initTable
+import kotlinx.coroutines.flow.Flow
+import org.jetbrains.exposed.sql.*
+import org.jetbrains.exposed.sql.transactions.transaction
+
+open class ExposedOneToManyKeyValueRepo<Key, Value>(
+    database: Database,
+    keyColumnAllocator: ColumnAllocator<Key>,
+    valueColumnAllocator: ColumnAllocator<Value>
+) : OneToManyKeyValueRepo<Key, Value>, ExposedReadOneToManyKeyValueRepo<Key, Value>(
+    database,
+    keyColumnAllocator,
+    valueColumnAllocator
+) {
+    protected val _onNewValue: BroadcastFlow<Pair<Key, Value>> = BroadcastFlow()
+    override val onNewValue: Flow<Pair<Key, Value>>
+        get() = _onNewValue
+    protected val _onValueRemoved: BroadcastFlow<Pair<Key, Value>> = BroadcastFlow()
+    override val onValueRemoved: Flow<Pair<Key, Value>>
+        get() = _onValueRemoved
+    protected val _onDataCleared: BroadcastFlow<Key> = BroadcastFlow()
+    override val onDataCleared: Flow<Key>
+        get() = _onDataCleared
+
+    override fun onInit() { initTable() }
+
+    override suspend fun add(k: Key, v: Value) {
+        transaction(database) {
+            insert {
+                it[keyColumn] = k
+                it[valueColumn] = v
+            }
+        }.also { _onNewValue.send(k to v) }
+    }
+
+    override suspend fun remove(k: Key, v: Value) {
+        transaction(database) {
+            deleteWhere { keyColumn.eq(k).and(valueColumn.eq(v)) }
+        }.also { _onValueRemoved.send(k to v) }
+    }
+
+    override suspend fun clear(k: Key) {
+        transaction(database) {
+            deleteWhere { keyColumn.eq(k) }
+        }.also { _onDataCleared.send(k) }
+    }
+}
+
+@Deprecated("Renamed", ReplaceWith("ExposedOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.onetomany.ExposedOneToManyKeyValueRepo"))
+typealias AbstractOneToManyExposedKeyValueRepo<Key, Value> = ExposedOneToManyKeyValueRepo<Key, Value>
+
+@Deprecated("Renamed", ReplaceWith("ExposedOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.onetomany.ExposedOneToManyKeyValueRepo"))
+typealias AbstractExposedOneToManyKeyValueRepo<Key, Value> = ExposedOneToManyKeyValueRepo<Key, Value>
diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/AbstractExposedReadOneToManyKeyValueRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/ExposedReadOneToManyKeyValueRepo.kt
similarity index 67%
rename from repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/AbstractExposedReadOneToManyKeyValueRepo.kt
rename to repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/ExposedReadOneToManyKeyValueRepo.kt
index 445ad25a04f..b1039a8363c 100644
--- a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/AbstractExposedReadOneToManyKeyValueRepo.kt
+++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/onetomany/ExposedReadOneToManyKeyValueRepo.kt
@@ -2,19 +2,20 @@ package dev.inmo.micro_utils.repos.exposed.onetomany
 
 import dev.inmo.micro_utils.pagination.*
 import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo
+import dev.inmo.micro_utils.repos.exposed.*
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.transactions.transaction
 
-typealias ColumnAllocator<T> = Table.() -> Column<T>
-
-abstract class AbstractExposedReadOneToManyKeyValueRepo<Key, Value>(
+open class ExposedReadOneToManyKeyValueRepo<Key, Value>(
+    override val database: Database,
     keyColumnAllocator: ColumnAllocator<Key>,
-    valueColumnAllocator: ColumnAllocator<Value>,
-    protected val database: Database
-) : ReadOneToManyKeyValueRepo<Key, Value>, Table() {
+    valueColumnAllocator: ColumnAllocator<Value>
+) : ReadOneToManyKeyValueRepo<Key, Value>, ExposedRepo, Table() {
     protected val keyColumn: Column<Key> = keyColumnAllocator()
     protected val valueColumn: Column<Value> = valueColumnAllocator()
 
+    override fun onInit() { initTable() }
+
     override suspend fun count(k: Key): Long = transaction(database) { select { keyColumn.eq(k) }.count() }
 
     override suspend fun count(): Long = transaction(database) { selectAll().count() }
@@ -46,5 +47,8 @@ abstract class AbstractExposedReadOneToManyKeyValueRepo<Key, Value>(
     }
 }
 
-@Deprecated("Renamed", ReplaceWith("AbstractExposedReadOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.onetomany.AbstractExposedReadOneToManyKeyValueRepo"))
-typealias AbstractOneToManyExposedReadKeyValueRepo<Key, Value> = AbstractExposedReadOneToManyKeyValueRepo<Key, Value>
+@Deprecated("Renamed", ReplaceWith("ExposedReadOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.onetomany.ExposedReadOneToManyKeyValueRepo"))
+typealias AbstractOneToManyExposedReadKeyValueRepo<Key, Value> = ExposedReadOneToManyKeyValueRepo<Key, Value>
+
+@Deprecated("Renamed", ReplaceWith("ExposedReadOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.exposed.onetomany.ExposedReadOneToManyKeyValueRepo"))
+typealias AbstractExposedReadOneToManyKeyValueRepo<Key, Value> = ExposedReadOneToManyKeyValueRepo<Key, Value>