0
0

# Doma2を使ってみる(その4)

Posted at

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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0