0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-04-08

Doma2を使ってみる(その3)

主要なクラス

名称未設定ファイル-ページ2.drawio (3).png

基本クラス

Doma では、データベースのカラム型にマッピング可能なJava型を 基本クラス と呼びます。

エンティティクラスやドメインクラス、DAOインターフェースで使用する

ドメインクラス

ドメインクラスは、カラムにマップできるユーザー定義のクラスです。ドメインクラスの使用はオプションです。

エンティティクラスやDAOインターフェースで使用する

内部ドメインクラス

クラスに @Domain アノテーションを付けられる場合のみ、内部ドメインクラスとして扱われます。

外部ドメインクラス

クラスに @Domain アノテーションを付けられない場合、外部ドメインクラスとして扱われます。

エンティティクラス

エンティティクラスはデータベースのテーブルまたはクエリの結果セットに対応します。

DAOインターフェース

DAOインターフェースは、データベースにアクセスするためのメソッドを宣言します。

クエリ

検索

SELECTステートメントを使用して検索を実行するには、DAOメソッドに @Select アノテーションを付けます。

検索条件

検索条件にはメソッドのパラメータを使用します。使用可能なパラメータの型は次のとおりです。
  • 基本クラス
  • ドメインクラス
  • 任意の型
  • 基本クラス や ドメインクラス や任意の型を要素とするjava.util.Optional
  • 基本クラス や ドメインクラス や任意の型を要素とするjava.util.Iterable
  • java.util.OptionalInt
  • java.util.OptionalLong
  • java.util.OptionalDouble
基本クラスで検索してみる

テーブルの作成

sql schema.sql
create table t_product (
    id varchar(20) primary key,
    name varchar(100),
    price integer,
    stock integer
);

テストデータの投入

sql data.sql
insert into t_product (id, name, price, stock) values ('p01', '消しゴム', 100, 10);

内部ドメインクラス

// 内部ドメインクラス
@Domain(valueType = String::class)
data class ProductId(val value: String)

DAOインターフェース

@Dao
@ConfigAutowireable
interface ProductDao {
    @Select
    fun selectById(id: String): ProductEntity // 検索条件に基本クラスを使用
}

SQLファイル

sql selectById.sql
select * from t_product where id = /* id */'1'

mainメソッド

@ComponentScan(basePackages = ["com.okr.shopping", "org.seasar.doma"])
@Configuration
class ShoppingApplication {

    @Bean
    fun dataSource(): DataSource {
        val dataSource = EmbeddedDatabaseBuilder()
                .addScripts("schema.sql", "data.sql")
                .setType(EmbeddedDatabaseType.H2).build()
        return dataSource
    }
}

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("[外部ドメインクラスでの検索結果]\nproductId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
}

実行結果

> Task :bootRun
17:50:32.080 [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'
17:50:32.173 [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
内部ドメインクラスで検索してみる

内部ドメインクラス
Kotlinでドメインクラスを作る場合は

// 内部ドメインクラス
@Domain(valueType = String::class)
data class ProductId(val value: String)

DAOインターフェース

@Dao
@ConfigAutowireable
interface ProductDao {
    @Select
    fun selectByProductId(productId: ProductId): ProductEntity // 検索条件にドメインクラスを使用
}

SQLファイル

sql selectByProductId.sql
select * from t_product where id = /* productId */'1'

mainメソッド

@ComponentScan(basePackages = ["com.okr.shopping", "org.seasar.doma"])
@Configuration
class ShoppingApplication {

    @Bean
    fun dataSource(): DataSource {
        val dataSource = EmbeddedDatabaseBuilder()
            .addScripts("schema.sql", "data.sql")
            .setType(EmbeddedDatabaseType.H2).build()
        return dataSource
    }
}

fun main(args: Array<String>) {
    val context: ApplicationContext = AnnotationConfigApplicationContext(
        ShoppingApplication::class.java)
    val productDao: ProductDao = context.getBean(ProductDao::class.java)
    
    val domainProductId = ProductId("p01")
    val product2: ProductEntity = productDao.selectByProductId(domainProductId)

    System.out.println("[ドメインクラスでの検索結果]\nproductId:" + product2.id + "\nname:" + product2.name + "\nprice:" + product2.price +"\nstock:" + product2.stock)
}

実行結果

> Task :bootRun
17:50:32.080 [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'
17:50:32.173 [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
外部ドメインクラスで検索してみる

外部ドメインクラス

// 外部ドメインクラス
data class ProductId(val value: String)

DomainConvertersクラス

@DomainConverters(ProductIdConverter::class)
class DomainConvertersProvider

ExternalDomainクラス

@ExternalDomain
class ProductIdConverter: DomainConverter<ProductId, String> {
    override fun fromDomainToValue(productId: ProductId): String {
        return productId.value
    }

    override fun fromValueToDomain(value: String): ProductId {
        return ProductId(value)
    }
}

build.gradle.kts

// 以下を追加
kapt {
    arguments {
        arg("doma.domain.converters", "com.okr.shopping.infla.doma.domain.DomainConvertersProvider")
    }
}

DAOインターフェース

@Dao
@ConfigAutowireable
interface ProductDao {
    @Select
    fun selectByProductId(productId: ProductId): ProductEntity // 検索条件に外部ドメインクラスを使用
}

SQLファイル

sql selectByProductId.sql
select * from t_product where id = /* productId */'1'

mainメソッド

@ComponentScan(basePackages = ["com.okr.shopping", "org.seasar.doma"])
@Configuration
class ShoppingApplication {

    @Bean
    fun dataSource(): DataSource {
        val dataSource = EmbeddedDatabaseBuilder()
            .addScripts("schema.sql", "data.sql")
            .setType(EmbeddedDatabaseType.H2).build()
        return dataSource
    }
}

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("[任意の型での検索結果]\nproductId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
}

実行結果

> Task :bootRun
18:35:27.951 [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'
18:35:28.038 [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
任意の型で検索してみる

任意の型

class Product : Serializable {
    var id: String? = null
    var name: String? = null
    var price: Int? = null
    var stock: Int? = null
}

DAOインターフェース

@Dao
@ConfigAutowireable
interface ProductDao {
    @Select
    fun selectByProduct(product: Product): ProductEntity// 検索条件に任意のクラスを使用
}

SQLファイル

sql selectByProductId.sql
select * from t_product where id = /* product.id */'1'

mainメソッド

@ComponentScan(basePackages = ["com.okr.shopping", "org.seasar.doma"])
@Configuration
class ShoppingApplication {

    @Bean
    fun dataSource(): DataSource {
        val dataSource = EmbeddedDatabaseBuilder()
            .addScripts("schema.sql", "data.sql")
            .setType(EmbeddedDatabaseType.H2).build()
        return dataSource
    }
}

fun main(args: Array<String>) {
    val context: ApplicationContext = AnnotationConfigApplicationContext(
        ShoppingApplication::class.java)
    val productDao: ProductDao = context.getBean(ProductDao::class.java)

    val product: ProductEntity = productDao.selectByProduct(Product().apply {
        id = "p01"
    })

    System.out.println("[任意の型での検索結果]\nproductId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
}

実行結果

> Task :bootRun
16:32:50.173 [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:32:50.260 [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
IN句で検索してみる

DAOインターフェース

@Dao
@ConfigAutowireable
interface ProductDao {

    @Select
    fun selectByIds(ids: List<String>): List<ProductEntity> // 検索条件にListを使用
}

SQLファイル

sql selectByIds.sql
select * from t_product where id in /* ids */('1', '2')

mainメソッド

fun main(args: Array<String>) {
    val context: ApplicationContext = AnnotationConfigApplicationContext(
            ShoppingApplication::class.java)
    val productDao: ProductDao = context.getBean(ProductDao::class.java)

    val products: List<ProductEntity> = productDao.selectByIds(listOf("p01", "p02", "p03"))
    products.forEach { product ->
        System.out.println("[任意の型での検索結果]\nproductId:" + product.id + "\nname:" + product.name + "\nprice:" + product.price +"\nstock:" + product.stock)
    }
}

実行結果

> Task :bootRun
16:41:11.977 [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:41:12.069 [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
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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?