Exposed
Exposed copied to clipboard
Oracle JDBC throws null expection on DAO create
I am hitting the following exception:
java.lang.NullPointerException: Cannot read the array length because "<local1>" is null
at oracle.jdbc.driver.OraclePreparedStatement.registerReturnParamsForAutoKey(OraclePreparedStatement.java:11907)
at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2024)
at oracle.jdbc.driver.OraclePreparedStatement.addBatch(OraclePreparedStatement.java:10058)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.addBatch(OraclePreparedStatementWrapper.java:1002)
at org.jetbrains.exposed.sql.statements.jdbc.JdbcPreparedStatementImpl.addBatch(JdbcPreparedStatementImpl.kt:21)
at org.jetbrains.exposed.sql.statements.Statement.executeIn$exposed_core(Statement.kt:54)
at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:138)
at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:124)
at org.jetbrains.exposed.sql.statements.Statement.execute(Statement.kt:28)
at org.jetbrains.exposed.sql.QueriesKt.executeBatch(Queries.kt:179)
at org.jetbrains.exposed.sql.QueriesKt.batchInsert(Queries.kt:108)
at org.jetbrains.exposed.sql.QueriesKt.batchInsert(Queries.kt:94)
at org.jetbrains.exposed.sql.QueriesKt.batchInsert$default(Queries.kt:89)
at org.jetbrains.exposed.dao.EntityCache$flushInserts$ids$1.invoke(EntityCache.kt:184)
at org.jetbrains.exposed.dao.EntityCache$flushInserts$ids$1.invoke(EntityCache.kt:183)
at org.jetbrains.exposed.dao.EntityLifecycleInterceptorKt.executeAsPartOfEntityLifecycle(EntityLifecycleInterceptor.kt:18)
at org.jetbrains.exposed.dao.EntityCache.flushInserts$exposed_dao(EntityCache.kt:183)
at org.jetbrains.exposed.dao.EntityCache.flush(EntityCache.kt:138)
at org.jetbrains.exposed.dao.EntityCache.flush(EntityCache.kt:107)
at org.jetbrains.exposed.dao.EntityCacheKt.flushCache(EntityCache.kt:243)
at org.jetbrains.exposed.dao.EntityLifecycleInterceptor.beforeCommit(EntityLifecycleInterceptor.kt:73)
at org.jetbrains.exposed.sql.Transaction.commit(Transaction.kt:67)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.inTopLevelTransaction$run(ThreadLocalTransactionManager.kt:190)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.access$inTopLevelTransaction$run(ThreadLocalTransactionManager.kt:1)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$inTopLevelTransaction$1.invoke(ThreadLocalTransactionManager.kt:215)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.keepAndRestoreTransactionRefAfterRun(ThreadLocalTransactionManager.kt:223)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.inTopLevelTransaction(ThreadLocalTransactionManager.kt:214)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$transaction$1.invoke(ThreadLocalTransactionManager.kt:165)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.keepAndRestoreTransactionRefAfterRun(ThreadLocalTransactionManager.kt:223)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:135)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:132)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction$default(ThreadLocalTransactionManager.kt:131)
This is caused by running the following code:
transaction {
HostAlias.new {
this.ipAddress = ipAddress
this.hostnamesString = hostNames.joinToString(",")
this.description = parameters[DescriptionParameter]?.trim()
}
}
The table is defined as:
object HostAliases : IdTable<Long>("host_aliases") {
override val id : org.jetbrains.exposed.sql.Column<EntityID<Long>> = long("id").autoIncrement(SEQUENCE_NAME).entityId()
override val primaryKey : PrimaryKey = PrimaryKey(id)
val ipAddress : org.jetbrains.exposed.sql.Column<String> = varchar("ip_address",512).uniqueIndex()
val description : org.jetbrains.exposed.sql.Column<String?> = text("description", eagerLoading = true).nullable()
val hostnames : org.jetbrains.exposed.sql.Column<String> = text("hostnames", eagerLoading = true)
}
class HostAlias(id: EntityID<Long>) : LongEntity(id) {
var ipAddress by HostAliases.ipAddress
var hostnamesString by HostAliases.hostnames
override var description by HostAliases.description
The error doesn't happen when I run the code with h2, only on an oracle db. Which leads me to believe that I am hitting some corner case bug with Oracle
I found a work around to this problem. It looks like oracle is not able to do batch updates with auto generated id values. So I instead inserted through DSL and then did a get on the id:
transaction {
val id = HostAliases.insertAndGetId {
it[id] = flexlineSequence.nextLongVal()
it[HostAliases.ipAddress] = ipAddress
it[hostnames] = hostNames.joinToString(",")
it[description] = parameters[DescriptionParameter]?.trim()
}
HostAlias.findById(id)
}
So I believe that that is the root cause of this issue.
@flyingcircle I was not able to reproduce that exception using your example with current version 0.43.0.
Quite a bit has been fixed with Oracle over the last few months. Could you please confirm if it is still a problem for you using new() or if this issue can be closed?
If the problem persists with current version 0.44.0, please consider reopening this issue on YouTrack. If you do so, please also provide a minimally-reproducible sample, so we can attempt to investigate further.