雑にKotlinでSpringを触ったメモ。
2020/04/29
-
SpringにはSpringMVC, RESt, Fluxなどあるので混同しないように注意しなければならない
-
@Component
SprintBoot。 -
@Service
と@Repository
はSpringMVC -
data classでは、JPAにマッピングできない- 結論、できる
- https://www.baeldung.com/kotlin-jpa
- identityがないと起動時エラーになる。@Idとかを付与しよう
-
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’entityManagerFactory’ defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.example.demo.Customer
-
- dataclassではどうしてもNotNull型では定義できない
-
data classでは、バリデーションが効かない?
- 結論、できる
- https://qiita.com/wrongwrong/items/8120faeb9f7498f925c5
-
Javaではfield:無しでもバリデーションが行えますが、Data Classではこれを付けなければ正常にバリデーションができません。`
- 結論、できる
-
バリデーション
- バリデーションは
Bean validation
というらしい - NotNullとかNotEmptyとかは違いがあるみたい
- @NotNullを付与したパラメータもNullableで受ける
- ネスとしたオブジェクトのバリデーションは該当プロパティに
@Valid
- 基本、Beenのバリデーションは、
@Valid
があった際に処理されるみたい
- 基本、Beenのバリデーションは、
- バリデーションは
-
リレーション
- 作れた
- OneToManyとかManyToManyとか
- fetchとcascadeは未調査
-
JPAのクエリをみたい
- https://www.baeldung.com/sql-logging-spring-boot
spring.jpa.properties.hibernate.format_sql=true
- しかしこれはパフォーマンス微妙
- ロギング経由
- https://www.baeldung.com/sql-logging-spring-boot
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
-
foodRepsitory.findAll()
- デフォルトではlazyローディング
@OneToOne(fetch = FetchType.EAGER)
でまとめて取得できると思ったけど無理- 方法がわからない
-
クリーンアーキテクチャ
- DIどうする?
- @Serviceとか@Repositoryとか使う?
- これはSpringMVCの機能なので、RESTの場合は使えない?使わない方がいい
- https://qiita.com/daisuzz/items/3e0cef338738143314bd
- interfaceを継承しているクラスに@Componentを付与
デフォルトコンストラクタのうち、引数が0のものがないとbeenの生成が動かないので注意- これはだめ→
class FoodInteractor(createdAt: LocalDateTime) : FoodBoundary {...
- これはだめ→
- できてないと beenの生成時にエラーが出る
-
Parameter 4 of constructor in com.example.demo.interfaces.RestSampleController required a bean of type ‘com.example.demo.application.FoodBoundary’ that could not be found.`
- @RestControllerでは、
- コンストラクタに加えておけば勝手に注入してくれる
- ただし、引数がないコンストラクタの場合のみ可能だったはず
private val foodBoundary: FoodBoundary
- @Autowiredを使ってプロパティとして定義しておく
@Autowired private lateinit var boundary: FoodBoundary
- どちらも同じインスタンスを参照していることに注意
- コンストラクタに加えておけば勝手に注入してくれる
- DIどうする?
-
時間関係は、LocalDateTimeとLocalDateがカラムとして使える
- https://www.baeldung.com/spring-date-parameters
- JSONの値は、デフォルトではiSOを使う必要がある
- 例えば
2020-04-30T00:26:50.91601
- https://stackoverflow.com/a/40330249/10040146
- 例えば
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
を使うことでJSONとBeanとの変換ができる
-
created_atは Hibernateなら
@CreationTimestamp
と@UpdateTimestamp
が利用できる -
HibernateとかJPAの違いとか
-
JPA=Java Persistence API
-
Hibernateは最も成熟したツール?と書かれていたが???
-
Spring Restでエラー
-
Before Spring 3.2, the two main approaches to handling exceptions in a Spring MVC application were: HandlerExceptionResolver or the @ExceptionHandler annotation. Both of these have some clear downsides.
- https://www.baeldung.com/exception-handling-for-rest-with-spring
-
-
@oneToMany
でエラー-
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’entityManagerFactory’ defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Collection has neither generic type or OneToMany.targetEntity() defined: com.example.demo.application.Customer.logs`
- https://qiita.com/rinp/items/e1713e568a4eb79391e5
- ListではなくMutableListを使う必要があったため
-
-
コンストラクタ
- セカンダリコンストラクタは、
this()
を継承する必要がある
- セカンダリコンストラクタは、
-
OutputBoundaryの返り値は
Any
にせざるを得ない!?!?- responseはControllerでするため、OutputBoundaryやInteractorは何かしらをreturnしなければならない
-
ほかにもちょこちょこAnyが出てきてしまった🚛
Controller
だとResponseEntity.ok(customer)
とかInputBoundary
だとfun purchase(customerId: Int, foodId: Int): Any
とか
-
どうすれば良い….
- そもそも、
PurchaseOutput
はUsecase層だから知っててOKと気づいた - なので
- Controllerに
PurchaseOutput
が出てきてもOK - Interactorに
PurchaseOutput
が出てきてもOK
- Controllerに
- そもそも、
2020/05/04
-
gradleの種類について
- これが分かりやすい
- https://www.baeldung.com/gradle-build-settings-properties
- setting.gradleはマルチプロジェクトにおいて必要
- シングルの場合はオプション。削除しても問題ない
-
RESTのドキュメントを自動生成したい
- Spring rest-docがそれにあたる
- テストとしてコードを書かなければならない
- ドキュメントからコードは、swaggerが最強
- APIBlueprintはあまりメジャーではなかった
- モデルまで出力してくれる
- オンラインのswaggerエディタでよくね?
- https://stoplight.io/studio/
- 1人25ドル
- https://stoplight.io/studio/
- Spring rest-docがそれにあたる
-
Kotlinの
in
とout
- 共変性のinと反変性のout
- ジェネリクスをもったものをキャストする際に利用される。
-
Dockerイメージ化
- こちらを参考に→https://spring.io/guides/gs/spring-boot-docker/
- gradleでビルド
# syntax=docker/dockerfile:experimental
FROM openjdk:14-jdk AS build
WORKDIR /workspace/app
COPY . /workspace/app
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean build
- jarファイル実行
FROM openjdk:14-jdk
COPY --from=build /workspace/app/build/libs/demo-0.0.1-SNAPSHOT.jar demo-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java","-jar", "demo-0.0.1-SNAPSHOT.jar"]
- 結局 `./gradle bootRun`でよかったんじゃないの?という気しかしない
-
HotReloading
- こちらに書いてあった→https://stackoverflow.com/a/12744431/10040146
- 1.IDEA(IntelliJ)のプラグインをgradleに読み込ませる
val developmentOnly by configurations.creating
developmentOnly("org.springframework.boot:spring-boot-devtools")
- 2.main関数横の再生マークから起動せずに、gradleから起動設定をする
Edit Configuration
- configをAdd
- gradleProjectは現在のものを選択
- Tasksは
bootRun
- Apply
- configを登録後、起動
- 3.kotlinファイル書き換えたりSpringのアノテーション書き換えると自動でビルドされる
- どうやら編集したあとにカーソルを改行すると反映される?
- もともとtemplateはビルドの必要ないので自動で反映される
- 公式にも記述があった→https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/#using-boot-devtools-restart
-
exposed
- 記述中