From 1b60933742d34ad3cc255a86e3f27821273667fa Mon Sep 17 00:00:00 2001 From: Laurent Van der Linden Date: Mon, 16 Nov 2015 20:48:59 +0100 Subject: [PATCH] Kotlin 1.0.0-beta-2423 --- build.gradle | 2 +- src/main/kotlin/sqlbuilder/ResultSet.kt | 4 +- src/main/kotlin/sqlbuilder/Select.kt | 4 +- src/main/kotlin/sqlbuilder/SqlBuilder.kt | 12 +++++ .../sqlbuilder/impl/DefaultConfiguration.kt | 9 ++-- src/main/kotlin/sqlbuilder/impl/InsertImpl.kt | 5 +- src/main/kotlin/sqlbuilder/impl/SelectImpl.kt | 10 ++-- .../kotlin/sqlbuilder/impl/SqlBuilderImpl.kt | 30 ++++-------- src/main/kotlin/sqlbuilder/impl/UpdateImpl.kt | 41 ++--------------- .../sqlbuilder/impl/mappers/DoubleMapper.kt | 2 +- .../sqlbuilder/impl/mappers/FloatMapper.kt | 2 +- .../sqlbuilder/impl/mappers/LongMapper.kt | 2 +- .../sqlbuilder/impl/mappers/ShortMapper.kt | 2 +- .../meta/JavaFieldPropertyReference.kt | 4 +- .../meta/JavaGetterSetterPropertyReference.kt | 10 ++-- .../sqlbuilder/meta/StaticJavaResolver.kt | 46 +++---------------- 16 files changed, 62 insertions(+), 123 deletions(-) diff --git a/build.gradle b/build.gradle index 3d3aeab..7ba338f 100755 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.0.0-beta-1038' + ext.kotlin_version = '1.0.0-beta-2423' repositories { mavenCentral() } diff --git a/src/main/kotlin/sqlbuilder/ResultSet.kt b/src/main/kotlin/sqlbuilder/ResultSet.kt index 250d3c1..65cc390 100755 --- a/src/main/kotlin/sqlbuilder/ResultSet.kt +++ b/src/main/kotlin/sqlbuilder/ResultSet.kt @@ -1,5 +1,6 @@ package sqlbuilder +import sqlbuilder.impl.mappers.AnyMapper import sqlbuilder.mapping.ToObjectMappingParameters import java.io.Closeable import java.sql.SQLException @@ -13,8 +14,7 @@ class ResultSet(private val target: java.sql.ResultSet, private val configuratio @Suppress("UNCHECKED_CAST") @Throws(SQLException::class) public fun getObject(targetType: Class, index: Int): T? { - val objectMapperForType = configuration.objectMapperForType(targetType) ?: - throw PersistenceException("unknown bean property, unable to find matching SQL variant: " + targetType.name) + val objectMapperForType = configuration.objectMapperForType(targetType) ?: AnyMapper() return objectMapperForType.toObject(ToObjectMappingParameters(index, target, targetType)) as T } diff --git a/src/main/kotlin/sqlbuilder/Select.kt b/src/main/kotlin/sqlbuilder/Select.kt index 6adddee..0d2287f 100755 --- a/src/main/kotlin/sqlbuilder/Select.kt +++ b/src/main/kotlin/sqlbuilder/Select.kt @@ -188,7 +188,7 @@ interface Select { /** * Override the cursor direction or concurrency to allow eg. updatable resultsets - * @param type one of + * @param cursorType one of * ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or * ResultSet.TYPE_SCROLL_SENSITIVE @@ -197,7 +197,7 @@ interface Select { * ResultSet.CONCUR_UPDATABLE * @return the current Select statement */ - fun resultSetType(`type`: Int, concurrency: Int): Select + fun resultSetType(cursorType: Int, concurrency: Int): Select /** * Specifiy group by statement, eg. select.groupBy("group by aardvz") diff --git a/src/main/kotlin/sqlbuilder/SqlBuilder.kt b/src/main/kotlin/sqlbuilder/SqlBuilder.kt index 544754a..6f90397 100755 --- a/src/main/kotlin/sqlbuilder/SqlBuilder.kt +++ b/src/main/kotlin/sqlbuilder/SqlBuilder.kt @@ -19,9 +19,21 @@ public interface SqlBuilder { * @return the same bean with the id set */ public fun save(bean: T, vararg excludedFields: String): T + /** + * Start a transaction with default isolation. + */ public fun startTransaction() + /** + * Start a transaction using an isolationlevel other than TRANSACTION_READ_COMMITTED + * @param isolationLevel Connection.TRANSACTION_... + */ public fun startTransaction(isolationLevel: Int, readonly: Boolean) public fun commitTransaction() + /** + * This must be called in the a finally clause whenever you have started a transaction. + *
If commitTransaction has already been called, it will only cleanup resources, + * else it will rollback the transaction. + */ public fun endTransaction() public fun purgeCache(cacheId: String) public fun purgeAllCaches() diff --git a/src/main/kotlin/sqlbuilder/impl/DefaultConfiguration.kt b/src/main/kotlin/sqlbuilder/impl/DefaultConfiguration.kt index 8368c10..0ec2a71 100644 --- a/src/main/kotlin/sqlbuilder/impl/DefaultConfiguration.kt +++ b/src/main/kotlin/sqlbuilder/impl/DefaultConfiguration.kt @@ -21,7 +21,6 @@ public open class DefaultConfiguration : Configuration { protected fun registerDefaultMappers() { val dualPurposeMappers = listOf( - AnyMapper(), StringMapper(), CharMapper(), LongMapper(), @@ -45,7 +44,7 @@ public open class DefaultConfiguration : Configuration { } } - override var metaResolver: MetaResolver = StaticJavaResolver() + override var metaResolver: MetaResolver = StaticJavaResolver(this) var escapeCharacter: Char? = null public fun setEscapeCharacter(escapeCharacter: Char): Configuration { @@ -65,11 +64,13 @@ public open class DefaultConfiguration : Configuration { } override fun objectMapperForType(targetType: Class<*>): ToObjectMapper? { - return toObjectMappers.last { it.handles(targetType) } + val lastOrNull = toObjectMappers.lastOrNull { it.handles(targetType) } + println("mapper for type $targetType -> $lastOrNull") + return lastOrNull } override fun sqlMapperForType(targetType: Class<*>): ToSQLMapper? { - return toSQLMappers.last { it.handles(targetType) } + return toSQLMappers.lastOrNull { it.handles(targetType) } } override fun registerToObjectMapper(toObjectMapper: ToObjectMapper): DefaultConfiguration { diff --git a/src/main/kotlin/sqlbuilder/impl/InsertImpl.kt b/src/main/kotlin/sqlbuilder/impl/InsertImpl.kt index 9329926..84cd5cd 100755 --- a/src/main/kotlin/sqlbuilder/impl/InsertImpl.kt +++ b/src/main/kotlin/sqlbuilder/impl/InsertImpl.kt @@ -90,6 +90,7 @@ class InsertImpl(val backend: Backend): Insert { sql.append(")") sqlString = sql.toString() + logger.info(sqlString) cachedStatement = sqlCon.prepareStatement(sqlString, if (getkeys) Statement.RETURN_GENERATED_KEYS else java.sql.Statement.NO_GENERATED_KEYS) @@ -103,7 +104,7 @@ class InsertImpl(val backend: Backend): Insert { for ((index,property) in properties.withIndex()) { - logger.debug("setInsertParameter " + property.name + " <" + property.classType.getName() + ">") + logger.debug("setInsertParameter " + property.name + " <" + property.classType.name + ">") sqlConverter.setParameter(cachedStatement!!, values[property], index + 1, property.classType, null) } @@ -112,7 +113,7 @@ class InsertImpl(val backend: Backend): Insert { if (getkeys) { try { var key: Long = 0; - val keys = cachedStatement!!.getGeneratedKeys() + val keys = cachedStatement!!.generatedKeys if (keys != null) { if (keys.next()) { key = keys.getLong(1) diff --git a/src/main/kotlin/sqlbuilder/impl/SelectImpl.kt b/src/main/kotlin/sqlbuilder/impl/SelectImpl.kt index 28297d3..327500b 100755 --- a/src/main/kotlin/sqlbuilder/impl/SelectImpl.kt +++ b/src/main/kotlin/sqlbuilder/impl/SelectImpl.kt @@ -68,7 +68,7 @@ class SelectImpl(val backend: Backend) : Select { orderBy = column orderAscending = ascending } else { - throw IllegalArgumentException("can't order by <" + column + ">") + throw IllegalArgumentException("can't order by <$column>") } return this } @@ -120,7 +120,7 @@ class SelectImpl(val backend: Backend) : Select { if (result.size > 1) { throw IncorrectResultSizeException("more than 1 result") } - return result.get(0) + return result[0] } return null } @@ -210,7 +210,7 @@ class SelectImpl(val backend: Backend) : Select { if (list.size > 1) { throw IncorrectResultSizeException("more than 1 result") } - return list.get(0) + return list[0] } return null } @@ -388,8 +388,8 @@ class SelectImpl(val backend: Backend) : Select { return this } - override fun resultSetType(`type`: Int, concurrency: Int): Select { - this.cursorType = `type` + override fun resultSetType(cursorType: Int, concurrency: Int): Select { + this.cursorType = cursorType this.cursorConcurrency = concurrency return this } diff --git a/src/main/kotlin/sqlbuilder/impl/SqlBuilderImpl.kt b/src/main/kotlin/sqlbuilder/impl/SqlBuilderImpl.kt index e05424d..0165064 100755 --- a/src/main/kotlin/sqlbuilder/impl/SqlBuilderImpl.kt +++ b/src/main/kotlin/sqlbuilder/impl/SqlBuilderImpl.kt @@ -51,7 +51,7 @@ public class SqlBuilderImpl(private val dataSource: DataSource) : SqlBuilder, Ba if (keys.size == 1 && keys[0] == "id") { val idField = metaResolver.findField("id", bean.javaClass) if (idField == null) throw IllegalArgumentException("bean <${bean.javaClass}> has no id field") - idField.setAccessible(true) + idField.isAccessible = true val valueBefore = idField.get(bean) if (valueBefore != null) { @@ -64,7 +64,7 @@ public class SqlBuilderImpl(private val dataSource: DataSource) : SqlBuilder, Ba try { idField.set(bean, id) } catch (e: Exception) { - throw PersistenceException("unable to set autogenerated id on " + bean.javaClass.getName(), e) + throw PersistenceException("unable to set autogenerated id on " + bean.javaClass.name, e) } } } else { @@ -78,7 +78,7 @@ public class SqlBuilderImpl(private val dataSource: DataSource) : SqlBuilder, Ba try { var connection = txConnections.get() if (connection == null) { - connection = dataSource.getConnection() + connection = dataSource.connection } return connection!! } catch (e: SQLException) { @@ -87,27 +87,20 @@ public class SqlBuilderImpl(private val dataSource: DataSource) : SqlBuilder, Ba } - /** - * Start a transaction with default isolation. - */ override fun startTransaction() { startTransaction(-1, false) } - /** - * Start a transaction using an isolationlevel other than TRANSACTION_READ_COMMITTED - * @param isolationLevel Connection.TRANSACTION_... - */ override fun startTransaction(isolationLevel: Int, readonly: Boolean) { try { var connection = txConnections.get() if (connection == null) { - connection = dataSource.getConnection() - if (isolationLevel >= 0) connection!!.setTransactionIsolation(isolationLevel) - connection!!.setAutoCommit(false) + connection = dataSource.connection + if (isolationLevel >= 0) connection!!.transactionIsolation = isolationLevel + connection!!.autoCommit = false txConnections.set(connection) } - connection.setReadOnly(readonly) + connection.isReadOnly = readonly } catch (e: SQLException) { throw PersistenceException(e.message, e) } @@ -120,7 +113,7 @@ public class SqlBuilderImpl(private val dataSource: DataSource) : SqlBuilder, Ba txConnections.set(null) try { connection.commit() - connection.setAutoCommit(true) + connection.autoCommit = true } catch (ignore: SQLException) { } @@ -137,18 +130,13 @@ public class SqlBuilderImpl(private val dataSource: DataSource) : SqlBuilder, Ba } } - /** - * This must be called in the a finally clause whenever you have started a transaction. - *
If commitTransaction has already been called, it will only cleanup resources, - * else it will rollback the transaction. - */ override fun endTransaction() { val connection = txConnections.get() if (connection != null) { txConnections.set(null) try { connection.rollback() - connection.setAutoCommit(true) + connection.autoCommit = true } catch (ignore: SQLException) {} closeConnection(connection) diff --git a/src/main/kotlin/sqlbuilder/impl/UpdateImpl.kt b/src/main/kotlin/sqlbuilder/impl/UpdateImpl.kt index abb4bff..6ba20a3 100755 --- a/src/main/kotlin/sqlbuilder/impl/UpdateImpl.kt +++ b/src/main/kotlin/sqlbuilder/impl/UpdateImpl.kt @@ -51,7 +51,7 @@ class UpdateImpl(private val backend: Backend): Update { if (entity == null) entity = metaResolver.getTableName(bean.javaClass) entity = backend.configuration.escapeEntity(entity) - if (keys.size == 0) { + if (keys.isEmpty()) { throw PersistenceException("cannot update bean without a list of keys") } @@ -100,10 +100,10 @@ class UpdateImpl(private val backend: Backend): Update { } if (updates != 1) { - throw PersistenceException("updateBean resulted in " + updates + " updated rows instead of 1 using <" + sql + "> with bean " + bean) + throw PersistenceException("updateBean resulted in $updates updated rows instead of 1 using <$sql> with bean $bean") } } catch (sqlx: SQLException) { - throw PersistenceException("update <" + sql + "> failed", sqlx) + throw PersistenceException("update <$sql> failed", sqlx) } } finally { @@ -111,32 +111,14 @@ class UpdateImpl(private val backend: Backend): Update { } } - /** - * Custom update that allows null parameters due to the types argument. - * @param sql statement - * @return updated rows - */ public override fun updateStatement(sql: String): Int { return updateStatement(sql, null, null) } - /** - * Custom update that allows null parameters due to the types argument. - * @param sql statement - * @param parameters parameters objects - * @return updated rows - */ public override fun updateStatement(sql: String, vararg parameters: Any): Int { return updateStatement(sql, parameters, null) } - /** - * Custom update that allows null parameters due to the types argument. - * @param sql statement - * @param parameters parameters objects - * @param types array of java.sql.Types - * @return updated rows - */ public override fun updateStatement(sql: String, parameters: Array?, types: IntArray?): Int { logger.info(sql) @@ -168,14 +150,14 @@ class UpdateImpl(private val backend: Backend): Update { } } catch (ignore: AbstractMethodError) { } catch (sqlx: SQLException) { - throw PersistenceException("unable to retreive generated keys", sqlx) + throw PersistenceException("unable to retrieve generated keys", sqlx) } } rows } } catch (px: PersistenceException) { - throw PersistenceException("update <" + sql + "> failed with parameters " + Arrays.toString(parameters), px) + throw PersistenceException("update <$sql> failed with parameters ${Arrays.toString(parameters)}", px) } @@ -186,13 +168,6 @@ class UpdateImpl(private val backend: Backend): Update { } } - /** - * Special updatestatement that throws PersistenceException if updated rows do not match. - * @param sql - * @param expectedUpdateCount - * @param parameters - * @return updated rows if matching the expected - */ public override fun updateStatementExpecting(sql: String, expectedUpdateCount: Int, vararg parameters: Any): Int { val updates = updateStatement(sql, parameters, null) if (updates != expectedUpdateCount) { @@ -204,12 +179,6 @@ class UpdateImpl(private val backend: Backend): Update { return updates } - /** - * store any generated id after executing the update statement (which should be an insert in this case) - *
use getGeneratedKey to get the value afterwards - * @param cond - * @return - */ public override fun getKeys(cond: Boolean): Update { this.getkeys = cond return this diff --git a/src/main/kotlin/sqlbuilder/impl/mappers/DoubleMapper.kt b/src/main/kotlin/sqlbuilder/impl/mappers/DoubleMapper.kt index 0ee186c..f17f0e8 100644 --- a/src/main/kotlin/sqlbuilder/impl/mappers/DoubleMapper.kt +++ b/src/main/kotlin/sqlbuilder/impl/mappers/DoubleMapper.kt @@ -27,6 +27,6 @@ public class DoubleMapper : BiMapper { } override fun handles(targetType: Class<*>): Boolean { - return targetType == Double::class.java + return targetType == Double::class.java || targetType == java.lang.Double::class.java } } \ No newline at end of file diff --git a/src/main/kotlin/sqlbuilder/impl/mappers/FloatMapper.kt b/src/main/kotlin/sqlbuilder/impl/mappers/FloatMapper.kt index da9d97b..6dad7f8 100644 --- a/src/main/kotlin/sqlbuilder/impl/mappers/FloatMapper.kt +++ b/src/main/kotlin/sqlbuilder/impl/mappers/FloatMapper.kt @@ -27,6 +27,6 @@ public class FloatMapper : BiMapper { } override fun handles(targetType: Class<*>): Boolean { - return targetType == Double::class.java + return targetType == Float::class.java || targetType == java.lang.Float::class.java } } \ No newline at end of file diff --git a/src/main/kotlin/sqlbuilder/impl/mappers/LongMapper.kt b/src/main/kotlin/sqlbuilder/impl/mappers/LongMapper.kt index a88136a..8a15cbf 100644 --- a/src/main/kotlin/sqlbuilder/impl/mappers/LongMapper.kt +++ b/src/main/kotlin/sqlbuilder/impl/mappers/LongMapper.kt @@ -27,6 +27,6 @@ public class LongMapper : BiMapper { } override fun handles(targetType: Class<*>): Boolean { - return Boolean::class.java == targetType + return Long::class.java == targetType || java.lang.Long::class.java == targetType } } \ No newline at end of file diff --git a/src/main/kotlin/sqlbuilder/impl/mappers/ShortMapper.kt b/src/main/kotlin/sqlbuilder/impl/mappers/ShortMapper.kt index 34095db..1b5884d 100644 --- a/src/main/kotlin/sqlbuilder/impl/mappers/ShortMapper.kt +++ b/src/main/kotlin/sqlbuilder/impl/mappers/ShortMapper.kt @@ -27,6 +27,6 @@ public class ShortMapper : BiMapper { } override fun handles(targetType: Class<*>): Boolean { - return Short::class.java == targetType + return Short::class.java == targetType || java.lang.Short::class.java == targetType } } \ No newline at end of file diff --git a/src/main/kotlin/sqlbuilder/meta/JavaFieldPropertyReference.kt b/src/main/kotlin/sqlbuilder/meta/JavaFieldPropertyReference.kt index 29a0389..82ad72c 100755 --- a/src/main/kotlin/sqlbuilder/meta/JavaFieldPropertyReference.kt +++ b/src/main/kotlin/sqlbuilder/meta/JavaFieldPropertyReference.kt @@ -8,11 +8,11 @@ import java.lang.reflect.Field * Wrapper for bean property using java.lang.reflect.Field access. */ public class JavaFieldPropertyReference(override var name: String, private val field: Field, override var classType: Class<*>) : PropertyReference { - private val fieldType = field.getType()!! + private val fieldType = field.type!! override fun set(bean: Any, value: Any?) { try { - if (!(value == null && fieldType.isPrimitive())) { + if (!(value == null && fieldType.isPrimitive)) { field.set(bean, value) } } catch (e: Exception) { diff --git a/src/main/kotlin/sqlbuilder/meta/JavaGetterSetterPropertyReference.kt b/src/main/kotlin/sqlbuilder/meta/JavaGetterSetterPropertyReference.kt index 89675ef..15377d4 100755 --- a/src/main/kotlin/sqlbuilder/meta/JavaGetterSetterPropertyReference.kt +++ b/src/main/kotlin/sqlbuilder/meta/JavaGetterSetterPropertyReference.kt @@ -12,11 +12,11 @@ import java.lang.reflect.Method public class JavaGetterSetterPropertyReference(override var name: String, private val method: Method, override var classType: Class<*>) : PropertyReference { override fun set(bean: Any, value: Any?) { try { - if (!(value == null && classType.isPrimitive())) { + if (!(value == null && classType.isPrimitive)) { method.invoke(bean, value) } } catch (e: Exception) { - val signature = "${method.getName()}(${method.getParameterTypes()?.joinToString(",")})" + val signature = "${method.name}(${method.parameterTypes?.joinToString(",")})" throw PersistenceException("unable to set value $name to '$value' on bean $bean using setter <${signature}>, expected argument of type <${classType}>, but got <${value?.javaClass}>", e) } @@ -24,12 +24,12 @@ public class JavaGetterSetterPropertyReference(override var name: String, privat override fun get(bean: Any): Any? { try { - if (!method.isAccessible()) { - method.setAccessible(true) + if (!method.isAccessible) { + method.isAccessible = true } return method.invoke(bean) } catch (e: Exception) { - val signature = "${method.getName()}(${method.getParameterTypes()?.joinToString(",")})" + val signature = "${method.name}(${method.parameterTypes?.joinToString(",")})" throw PersistenceException("unable to get value $name from bean $bean using getter $signature", e) } } diff --git a/src/main/kotlin/sqlbuilder/meta/StaticJavaResolver.kt b/src/main/kotlin/sqlbuilder/meta/StaticJavaResolver.kt index ee2cb59..d5d9a20 100755 --- a/src/main/kotlin/sqlbuilder/meta/StaticJavaResolver.kt +++ b/src/main/kotlin/sqlbuilder/meta/StaticJavaResolver.kt @@ -1,13 +1,9 @@ package sqlbuilder.meta +import sqlbuilder.Configuration import java.lang.reflect.Field import java.lang.reflect.Modifier -import java.math.BigDecimal -import java.sql.Timestamp -import java.util.Date -import java.util.HashSet -import java.util.LinkedList -import org.slf4j.LoggerFactory +import java.util.* /** * Scans for public static fields containing info about the tablename and primary key(s): @@ -21,7 +17,7 @@ import org.slf4j.LoggerFactory * * @author Laurent Van der Linden */ -public class StaticJavaResolver() : MetaResolver { +public class StaticJavaResolver(val configuration: Configuration) : MetaResolver { override fun getTableName(beanClass: Class<*>): String { try { val field = findField("TABLE", beanClass) @@ -85,6 +81,10 @@ public class StaticJavaResolver() : MetaResolver { return result } + private fun isSqlType(clazz: Class<*>): Boolean { + return configuration.objectMapperForType(clazz) != null + } + override fun findField(name: String, fieldType: Class<*>): Field? { try { return fieldType.getDeclaredField(name) @@ -111,36 +111,4 @@ public class StaticJavaResolver() : MetaResolver { return arrayOf("id") } - - companion object { - private val logger = LoggerFactory.getLogger(StaticJavaResolver::class.java) - - @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") - public fun isSqlType(fieldType: Class<*>): Boolean { - val isSqlType = String::class.java == fieldType || - Int::class.java == fieldType || - java.lang.Integer::class.java == fieldType || - Short::class.java == fieldType || - java.lang.Short::class.java == fieldType || - Double::class.java == fieldType || - Double::class.java == fieldType || - Long::class.java == fieldType || - java.lang.Long::class.java == fieldType || - Float::class.java == fieldType || - java.lang.Float::class.java == fieldType || - Char::class.java == fieldType || - Date::class.java == fieldType || - java.sql.Date::class.java == fieldType || - Timestamp::class.java == fieldType || - BigDecimal::class.java == fieldType || - ByteArray::class.java == fieldType || - Boolean::class.java == fieldType || - java.lang.Boolean::class.java == fieldType || - Enum::class.java.isAssignableFrom(fieldType) - if (!isSqlType) { - logger.debug("$fieldType is not a Sql type") - } - return isSqlType - } - } }