Doma2を使ってみる(その4)
検索2
単一レコードの検索
期待結果が1つである場合
DAO
@Dao
@ConfigAutowireable
interface ProductDao {
@Select
fun selectByProductId(productId: ProductId): ProductEntity
}
main関数
fun main(args: Array<String>) {
val context: ApplicationContext = AnnotationConfigApplicationContext(
ShoppingApplication::class.java)
val productDao: ProductDao = context.getBean(ProductDao::class.java)
val product: ProductEntity = productDao.selectByProductId(ProductId("p01"))
System.out.println("productId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
}
実行結果
> Task :bootRun
13:51:10.407 [main] INFO org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory -- Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
13:51:10.493 [main] WARN org.seasar.doma.boot.autoconfigure.DomaAutoConfiguration -- StandardDialect was selected because no explicit configuration and it is not possible to guess from 'spring.datasource.url property'
productId:p01
name:消しゴム
price:100
stock:10
検索結果が0件の場合
DAO
@Dao
@ConfigAutowireable
interface ProductDao {
@Select
fun selectByProductId(productId: ProductId): ProductEntity
}
main関数
fun main(args: Array<String>) {
val context: ApplicationContext = AnnotationConfigApplicationContext(
ShoppingApplication::class.java)
val productDao: ProductDao = context.getBean(ProductDao::class.java)
val product: ProductEntity = productDao.selectByProductId(ProductId("p011"))
System.out.println("productId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
}
実行結果
> Task :bootRun FAILED
13:57:54.858 [main] INFO org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory -- Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
13:57:54.946 [main] WARN org.seasar.doma.boot.autoconfigure.DomaAutoConfiguration -- StandardDialect was selected because no explicit configuration and it is not possible to guess from 'spring.datasource.url property'
4月 09, 2024 1:57:55 午後 com.okr.shopping.infla.doma.dao.ProductDaoImpl selectByProductId
情報: [DOMA2220] ENTER : CLASS=com.okr.shopping.infla.doma.dao.ProductDaoImpl, METHOD=selectByProductId
4月 09, 2024 1:57:55 午後 com.okr.shopping.infla.doma.dao.ProductDaoImpl selectByProductId
情報: [DOMA2076] SQL LOG : PATH=[META-INF/com/okr/shopping/infla/doma/dao/ProductDao/selectByProductId.sql],
select * from t_product where id = 'p011'
4月 09, 2024 1:57:55 午後 com.okr.shopping.infla.doma.dao.ProductDaoImpl selectByProductId
情報: [DOMA2221] EXIT : CLASS=com.okr.shopping.infla.doma.dao.ProductDaoImpl, METHOD=selectByProductId
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.okr.shopping.infla.doma.entity.ProductEntity.getId()" because "product" is null
at com.okr.shopping.ShoppingApplicationKt.main(ShoppingApplication.kt:47)
Execution failed for task ':bootRun'.
> Process 'command '/Users/okurashoichi/.sdkman/candidates/java/17.0.10-amzn/bin/java'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD FAILED in 1s
10 actionable tasks: 2 executed, 8 up-to-date
DAOのInterfaceは非NULLで書くことは可能だが、実装クラスはNULLを返すため、NullPointerExceptionが発生する。
戻り値の型が Optional でなく、結果件数が 0 の場合、null が返されます。
DAOのInterfaceでは単一レコードの検索
の場合、戻り値の型をNullableにすることが望ましい。
DAO
@Dao
@ConfigAutowireable
interface ProductDao {
@Select
fun selectByProductId(productId: ProductId): ProductEntity?//<=Nullable
}
【!ってなんだ】KotlinとJava、nullとPlatformType【NullableにNotNull】
単一が期待結果だったが、検索結果が複数であった場合
NonUniqueResultException
が発生する。
DAO
@Dao
@ConfigAutowireable
interface ProductDao {
@Select
fun selectByIds(ids: List<String>): ProductEntity
}
実行結果
エラー
> Task :bootRun FAILED
15:55:59.266 [main] INFO org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory -- Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
15:55:59.358 [main] WARN org.seasar.doma.boot.autoconfigure.DomaAutoConfiguration -- StandardDialect was selected because no explicit configuration and it is not possible to guess from 'spring.datasource.url property'
4月 09, 2024 3:55:59 午後 com.okr.shopping.infla.doma.dao.ProductDaoImpl selectByIds
情報: [DOMA2220] ENTER : CLASS=com.okr.shopping.infla.doma.dao.ProductDaoImpl, METHOD=selectByIds
4月 09, 2024 3:55:59 午後 com.okr.shopping.infla.doma.dao.ProductDaoImpl selectByIds
情報: [DOMA2076] SQL LOG : PATH=[META-INF/com/okr/shopping/infla/doma/dao/ProductDao/selectByIds.sql],
select * from t_product where id in ('p01', 'p02', 'p03')
4月 09, 2024 3:55:59 午後 com.okr.shopping.infla.doma.dao.ProductDaoImpl selectByIds
情報: [DOMA2222] THROW : CLASS=com.okr.shopping.infla.doma.dao.ProductDaoImpl, METHOD=selectByIds, EXCEPTION=org.seasar.doma.jdbc.NonUniqueResultException
Exception in thread "main" org.seasar.doma.jdbc.NonUniqueResultException: [DOMA2001] The SQL result is not a single row.
PATH=[META-INF/com/okr/shopping/infla/doma/dao/ProductDao/selectByIds.sql].
SQL=[].
at org.seasar.doma.internal.jdbc.command.AbstractSingleResultHandler.lambda$handle$0(AbstractSingleResultHandler.java:34)
at org.seasar.doma.internal.jdbc.command.ResultSetIterator.next(ResultSetIterator.java:58)
at org.seasar.doma.internal.jdbc.command.AbstractIterationHandler.iterate(AbstractIterationHandler.java:52)
at org.seasar.doma.internal.jdbc.command.AbstractIterationHandler.handle(AbstractIterationHandler.java:40)
at org.seasar.doma.internal.jdbc.command.AbstractSingleResultHandler.handle(AbstractSingleResultHandler.java:27)
at org.seasar.doma.jdbc.command.SelectCommand.handleResultSet(SelectCommand.java:100)
at org.seasar.doma.jdbc.command.SelectCommand.executeQuery(SelectCommand.java:92)
at org.seasar.doma.jdbc.command.SelectCommand.execute(SelectCommand.java:52)
at com.okr.shopping.infla.doma.dao.ProductDaoImpl.selectByIds(ProductDaoImpl.java:158)
at com.okr.shopping.ShoppingApplicationKt.main(ShoppingApplication.kt:46)
Execution failed for task ':bootRun'.
> Process 'command '/Users/okurashoichi/.sdkman/candidates/java/17.0.10-amzn/bin/java'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD FAILED in 2s
10 actionable tasks: 7 executed, 3 up-to-date
複数レコードの検索
検索結果が複数件を期待する場合、戻り値をListにする。
複数のレコードを検索する場合は、メソッドの戻り値の型に java.util.List を指定します。List の要素は以下の型になります。
実行結果が複数件の場合
DAO
@Dao
@ConfigAutowireable
interface ProductDao {
@Select
fun selectByIds(ids: List<String>): List<ProductEntity>
}
main関数
fun main(args: Array<String>) {
val context: ApplicationContext = AnnotationConfigApplicationContext(
ShoppingApplication::class.java)
val productDao: ProductDao = context.getBean(ProductDao::class.java)
val productList: List<ProductEntity> =
productDao.selectByIds(listOf("p01", "p02", "p03"))
productList.forEach { product ->
System.out.println("productId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
}
}
実行結果
16:03:13: 'bootRun' を実行中...
> Task :checkKotlinGradlePluginConfigurationErrors
> Task :domaCopyResourcesKotlin UP-TO-DATE
> Task :domaCopyResourcesJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :kaptGenerateStubsKotlin
> Task :kaptKotlin UP-TO-DATE
> Task :compileKotlin
w: file:///Users/okurashoichi/Github/study/shopping/src/main/kotlin/com/okr/shopping/ShoppingApplication.kt:41:10 Parameter 'args' is never used
> Task :compileJava
> Task :classes
> Task :resolveMainClassName
> Task :bootRun
16:03:15.491 [main] INFO org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory -- Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
16:03:15.584 [main] WARN org.seasar.doma.boot.autoconfigure.DomaAutoConfiguration -- StandardDialect was selected because no explicit configuration and it is not possible to guess from 'spring.datasource.url property'
productId:p01
name:消しゴム
price:100
stock:10
productId:p02
name:ノート
price:200
stock:20
productId:p03
name:pname03
price:300
stock:30
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 2s
検索結果が0件の場合
検索結果がない場合、空のリストが返されます。
main関数
fun main(args: Array<String>) {
val context: ApplicationContext = AnnotationConfigApplicationContext(
ShoppingApplication::class.java)
val productDao: ProductDao = context.getBean(ProductDao::class.java)
val productList: List<ProductEntity> =
productDao.selectByIds(listOf("p011", "p012", "p013"))
println("Listの中身の数:" + productList.size)
productList.forEach { product ->
println("productId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
}
}
実行結果
16:09:30: 'bootRun' を実行中...
> Task :checkKotlinGradlePluginConfigurationErrors
> Task :domaCopyResourcesKotlin UP-TO-DATE
> Task :domaCopyResourcesJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :kaptGenerateStubsKotlin
> Task :kaptKotlin UP-TO-DATE
> Task :compileKotlin
w: file:///Users/okurashoichi/Github/study/shopping/src/main/kotlin/com/okr/shopping/ShoppingApplication.kt:41:10 Parameter 'args' is never used
> Task :compileJava UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :resolveMainClassName
> Task :bootRun
16:09:31.640 [main] INFO org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory -- Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
16:09:31.733 [main] WARN org.seasar.doma.boot.autoconfigure.DomaAutoConfiguration -- StandardDialect was selected because no explicit configuration and it is not possible to guess from 'spring.datasource.url property'
Listの中身の数:0
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 1s