Skip to content
This repository was archived by the owner on Jan 20, 2023. It is now read-only.

Commit 7c8d213

Browse files
authored
Merge pull request #5 from k163377/feature
Add annotation that means "Use Non Null argument".
2 parents 48b9bd4 + 39061a7 commit 7c8d213

File tree

5 files changed

+133
-24
lines changed

5 files changed

+133
-24
lines changed

build.gradle.kts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group = "com.mapk"
9-
version = "0.3"
9+
version = "0.4"
1010

1111
java {
1212
sourceCompatibility = JavaVersion.VERSION_1_8
@@ -30,25 +30,29 @@ repositories {
3030
dependencies {
3131
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
3232
implementation(kotlin("reflect"))
33+
api("com.github.ProjectMapK:Shared:0.8")
3334
// 使うのはRowMapperのみなため他はexclude、またバージョンそのものは使う相手に合わせるためcompileOnly
3435
compileOnly(group = "org.springframework", name = "spring-jdbc", version = "5.2.4.RELEASE") {
3536
exclude(module = "spring-beans")
3637
exclude(module = "spring-jcl")
3738
exclude(module = "spring-tx")
3839
}
39-
api("com.github.ProjectMapK:Shared:0.7")
4040

4141
// https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter
4242
testImplementation(group = "org.junit.jupiter", name = "junit-jupiter", version = "5.6.0") {
4343
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
4444
}
4545
// https://mvnrepository.com/artifact/io.mockk/mockk
4646
testImplementation("io.mockk:mockk:1.9.3")
47+
48+
// テスト時には無いと困るため、別口でimplementation
49+
testImplementation(group = "org.springframework", name = "spring-jdbc", version = "5.2.4.RELEASE")
50+
// https://mvnrepository.com/artifact/com.h2database/h2
51+
testImplementation(group = "com.h2database", name = "h2", version = "1.4.200")
52+
4753
// 現状プロパティ名の変換はテストでしか使っていないのでtestImplementation
4854
// https://mvnrepository.com/artifact/com.google.guava/guava
4955
testImplementation(group = "com.google.guava", name = "guava", version = "28.2-jre")
50-
// テスト時には無いと困るため、別口でimplementation
51-
testImplementation(group = "org.springframework", name = "spring-jdbc", version = "5.2.4.RELEASE")
5256
}
5357

5458
tasks {

src/main/kotlin/com/mapk/krowmapper/ParameterForMap.kt

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,37 @@ import kotlin.reflect.jvm.jvmName
1717

1818
class ParameterForMap private constructor(
1919
val param: KParameter,
20-
private val name: String,
21-
kClazz: KClass<*>
20+
name: String,
21+
parameterKClazz: KClass<*>
2222
) {
23-
private val javaClazz: Class<*> = kClazz.java
24-
private val deserializer: KFunction<*>?
23+
private val objectGetter: (ResultSet) -> Any?
2524

2625
init {
27-
val deserializers = deserializerFromConstructors(kClazz) +
28-
deserializerFromStaticMethods(kClazz) +
29-
deserializerFromCompanionObject(kClazz)
26+
val deserializer = parameterKClazz.getDeserializer()
3027

31-
deserializer = when {
32-
deserializers.isEmpty() -> null
33-
deserializers.size == 1 -> deserializers.single()
34-
else -> throw IllegalArgumentException("Find multiple deserializer from ${kClazz.jvmName}")
35-
}
36-
}
28+
if (deserializer != null) {
29+
val targetClass = deserializer.parameters.single().type.classifier as KClass<*>
3730

38-
fun getObject(rs: ResultSet): Any? = when {
39-
javaClazz.isEnum -> EnumMapper.getEnum(javaClazz, rs.getString(name))
40-
else -> {
41-
val value: Any? = rs.getObject(name, javaClazz)
42-
deserializer?.call(value) ?: value
31+
objectGetter = {
32+
deserializer.call(it.getObject(name, targetClass.javaObjectType))
33+
}
34+
} else {
35+
val clazz = parameterKClazz.javaObjectType
36+
37+
objectGetter = if (clazz.isEnum) {
38+
{
39+
EnumMapper.getEnum(clazz, it.getString(name))
40+
}
41+
} else {
42+
{
43+
it.getObject(name, clazz)
44+
}
45+
}
4346
}
4447
}
4548

49+
fun getObject(rs: ResultSet): Any? = objectGetter(rs)
50+
4651
companion object {
4752
fun newInstance(param: KParameter, propertyNameConverter: (String) -> String = { it }): ParameterForMap {
4853
return ParameterForMap(
@@ -54,6 +59,18 @@ class ParameterForMap private constructor(
5459
}
5560
}
5661

62+
private fun <T : Any> KClass<T>.getDeserializer(): KFunction<T>? {
63+
val deserializers = deserializerFromConstructors(this) +
64+
deserializerFromStaticMethods(this) +
65+
deserializerFromCompanionObject(this)
66+
67+
return when {
68+
deserializers.isEmpty() -> null
69+
deserializers.size == 1 -> deserializers.single()
70+
else -> throw IllegalArgumentException("Find multiple deserializer from $jvmName")
71+
}
72+
}
73+
5774
private fun <T> Collection<KFunction<T>>.getDeserializerFromFunctions(): Collection<KFunction<T>> {
5875
return filter { it.annotations.any { annotation -> annotation is KColumnDeserializer } }
5976
.map { func ->

src/test/kotlin/com/mapk/krowmapper/DefaultValueTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class DefaultValueTest {
2727
Assertions.assertEquals(1, result.fooId)
2828
Assertions.assertEquals("default", result.barValue)
2929

30-
verify(exactly = 1) { resultSet.getObject("foo_id", Int::class.java) }
30+
verify(exactly = 1) { resultSet.getObject("foo_id", Integer::class.java) }
3131
verify(exactly = 0) { resultSet.getObject("bar_value", String::class.java) }
3232
}
3333
}

src/test/kotlin/com/mapk/krowmapper/SimpleMappingTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class SimpleMappingTest {
2727
assertEquals(1, result.fooId)
2828
assertEquals("str", result.strValue)
2929

30-
verify(exactly = 1) { resultSet.getObject("foo_id", Int::class.java) }
30+
verify(exactly = 1) { resultSet.getObject("foo_id", Integer::class.java) }
3131
verify(exactly = 1) { resultSet.getObject("str_value", String::class.java) }
3232
}
3333
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.mapk.krowmapper
2+
3+
import com.google.common.base.CaseFormat
4+
import javax.sql.DataSource
5+
import org.h2.jdbcx.JdbcDataSource
6+
import org.junit.jupiter.api.Assertions.assertEquals
7+
import org.junit.jupiter.api.BeforeAll
8+
import org.junit.jupiter.api.Test
9+
import org.junit.jupiter.api.TestInstance
10+
import org.springframework.jdbc.core.JdbcTemplate
11+
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource
12+
import org.springframework.jdbc.core.simple.SimpleJdbcInsert
13+
14+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
15+
class UseDBMappingTest {
16+
enum class FooStatus {
17+
active, archive, deleted
18+
}
19+
20+
data class Foo(
21+
val fooId: Int,
22+
val fooName: String,
23+
val fooStatus: FooStatus,
24+
val isBar: Boolean,
25+
val description: String?
26+
) {
27+
companion object {
28+
fun fooFactory(
29+
fooId: Int,
30+
fooName: String,
31+
fooStatus: FooStatus,
32+
isBar: String,
33+
description: String?
34+
) = Foo(
35+
fooId, fooName, fooStatus, isBar.toBoolean(), description
36+
)
37+
}
38+
}
39+
40+
data class FooInsert(
41+
val fooId: Int,
42+
val fooName: String,
43+
private val fooStatus: FooStatus,
44+
private val isBar: Boolean,
45+
val description: String?
46+
) {
47+
fun getFooStatus(): String = fooStatus.name
48+
fun getIsBar(): String = isBar.toString()
49+
}
50+
51+
lateinit var jdbcTemplate: JdbcTemplate
52+
53+
@BeforeAll
54+
fun beforeAll() {
55+
val dataSource: DataSource = JdbcDataSource().apply {
56+
setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS APP\\;SET SCHEMA APP;")
57+
}
58+
59+
jdbcTemplate = JdbcTemplate(dataSource)
60+
61+
jdbcTemplate.execute("""
62+
CREATE TABLE IF NOT EXISTS `foo_table` (
63+
`foo_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
64+
`foo_name` VARCHAR(255) NOT NULL,
65+
`foo_status` ENUM('active', 'archive', 'deleted') NOT NULL,
66+
`is_bar` ENUM('true', 'false') NOT NULL,
67+
`description` VARCHAR(1023) NULL DEFAULT NULL,
68+
PRIMARY KEY (`foo_id`)
69+
);
70+
""".trimIndent())
71+
72+
val data = FooInsert(10, "Foo", FooStatus.archive, false, null)
73+
74+
SimpleJdbcInsert(jdbcTemplate).withTableName("foo_table").execute(BeanPropertySqlParameterSource(data))
75+
}
76+
77+
@Test
78+
fun test() {
79+
val result = jdbcTemplate.query("SELECT * FROM foo_table", KRowMapper((Foo)::fooFactory) {
80+
CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, it)
81+
}).single()
82+
83+
assertEquals(
84+
Foo(10, "Foo", FooStatus.archive, false, null),
85+
result
86+
)
87+
}
88+
}

0 commit comments

Comments
 (0)