Skip to content

Instantly share code, notes, and snippets.

@usbharu
Last active September 1, 2022 06:15
Show Gist options
  • Save usbharu/bd1060d95c7b7325509f7f920935c109 to your computer and use it in GitHub Desktop.
Save usbharu/bd1060d95c7b7325509f7f920935c109 to your computer and use it in GitHub Desktop.
Kotlin + Exposed でSQLiteを使用しているときでもBatchInsertを使えるようにする拡張関数
fun <T : Table, E : Any> T.batchInsert(
data: Iterable<E>,
ignore: Boolean = false,
body: BatchInsertStatement.(E) -> Unit
): List<ResultRow> {
if (data.count() == 0) return emptyList()
val statement = object : SQLServerBatchInsertStatement(this, ignore) {
override fun prepareSQL(transaction: Transaction): String {
val values = arguments!!
val sql = if (values.isEmpty()) ""
else {
val output = table.autoIncColumn?.let { " RETURNING ${transaction.identity(it)} AS GENERATED_KEYS" }.orEmpty()
val toString = QueryBuilder(true).apply {
values.appendTo(prefix = "VALUES ") {
it.appendTo(prefix = "(", postfix = ")") { (col, value) ->
registerArgument(col, value)
}
}
values.appendTo(prefix = output) {}
}.toString()
toString.substring(0,toString.lastIndex-1)
}
return transaction.db.dialect.functionProvider.insert(isIgnore, table, values.firstOrNull()?.map { it.first }.orEmpty(), sql, transaction)
}
}
val result = java.util.ArrayList<ResultRow>()
fun BatchInsertStatement.handleBatchException(body: BatchInsertStatement.() -> Unit) {
try {
body()
} catch (e: Exception) {
execute(TransactionManager.current())
result += resultedValues.orEmpty()
e.printStackTrace()
}
}
for (element in data) {
statement.handleBatchException { addBatch() }
statement.handleBatchException {
body(element)
}
}
if (statement.arguments().isNotEmpty()) {
statement.execute(TransactionManager.current())
result += statement.resultedValues.orEmpty()
}
return result
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment