きり丸の技術日記

技術検証したり、資格等をここに残していきます。

LazyLoadのエンティティを取得しようとしてClass Not Foundが発生した(原因不明・Spring・MyBatis)

自宅で再現できなかったので原因はわかっていません。しかし、対策はうまくいったので残します。


MyBatisにてLazyLoadで取得したエンティティの子データをJavaでgetter経由で取得しようとしました。その時にClass Not Foundが発生しました。詳細なメッセージを読んでいくと、「User_$$_sas3qsdクラスから、Userクラスにキャストできません。User_$$_sas3qsdクラスをうまく読み込めなかったので、リロードしてください。」といった意図のメッセージが出ていました。ただし、メッセージの通りに再起動しても、うまくいきません。

この記事は、このメッセージを元に、色々と頑張ったメモです。

環境

  • Java
    • 11
  • Oracle
  • SpringBoot
  • MyBatis

※ 再現できなかったので、バージョンは特に記載しません。

原因(推測)

LazyLoadでDBからデータを取得しようとした時にLazyLoad用の設定が壊れていた。

対応

LazyLoadではなく、EagerLoadを使用する。

状況説明

  1. DBから親エンティティを取得していた
  2. なんやかんや
  3. 2分くらい処理
  4. 別の処理でコミット
  5. LombokのtoBuilderでデータコピー
  6. SerializationUtils#cloneでクローン
  7. 親エンティティの子データをLazyLoadしようとしたらエラーが発生

Class Not Found発生までに、色々と条件が複合している気がします。

  1. トランザクションがおかしい
  2. タイムアウトした?
  3. Update等々の更新後だとキャッシュが壊れて、更新前のトランザクションが動かなくなる?
  4. クローン処理で壊れた?

IntelliJ IDEAのデバッグログを見ながら検証し、既に取得したデータはUser@8860と表示されていましたが、該当の処理ではUser_$$_jvst8c5_1@8861となっていたので、LazyLoadが原因なのだろうと推測は立てることができました。

LazyLoadで、エンティティに対して動的なインナークラスが生まれ、ポインタへのアクセスを起点にインナークラスから親クラスを生成するのでしょう。そのインナークラスから親クラスを生成しようとしたら処理が空振りして、直接キャストしようとしたのかも。たぶん。

終わりに

発生したエラーメッセージが特殊すぎて、びっくりしました。

特殊な処理をしようとすると、エラーが複雑になりますね。経験値は増やしていきたいです。