自宅で再現できなかったので原因はわかっていません。しかし、対策はうまくいったので残します。
MyBatisにてLazyLoadで取得したエンティティの子データをJavaでgetter経由で取得しようとしました。その時にClass Not Found
が発生しました。詳細なメッセージを読んでいくと、「User_$$_sas3qsd
クラスから、User
クラスにキャストできません。User_$$_sas3qsd
クラスをうまく読み込めなかったので、リロードしてください。」といった意図のメッセージが出ていました。ただし、メッセージの通りに再起動しても、うまくいきません。
この記事は、このメッセージを元に、色々と頑張ったメモです。
環境
- Java
- 11
- Oracle
- SpringBoot
- MyBatis
※ 再現できなかったので、バージョンは特に記載しません。
原因(推測)
LazyLoadでDBからデータを取得しようとした時にLazyLoad用の設定が壊れていた。
対応
LazyLoad
ではなく、EagerLoad
を使用する。
状況説明
- DBから親エンティティを取得していた
- なんやかんや
- 2分くらい処理
- 別の処理でコミット
Lombok
のtoBuilderでデータコピーSerializationUtils#clone
でクローン- 親エンティティの子データをLazyLoadしようとしたらエラーが発生
Class Not Found
発生までに、色々と条件が複合している気がします。
- トランザクションがおかしい
- タイムアウトした?
Update
等々の更新後だとキャッシュが壊れて、更新前のトランザクションが動かなくなる?- クローン処理で壊れた?
IntelliJ IDEAのデバッグログを見ながら検証し、既に取得したデータはUser@8860
と表示されていましたが、該当の処理ではUser_$$_jvst8c5_1@8861
となっていたので、LazyLoad
が原因なのだろうと推測は立てることができました。
LazyLoad
で、エンティティに対して動的なインナークラスが生まれ、ポインタへのアクセスを起点にインナークラスから親クラスを生成するのでしょう。そのインナークラスから親クラスを生成しようとしたら処理が空振りして、直接キャストしようとしたのかも。たぶん。
終わりに
発生したエラーメッセージが特殊すぎて、びっくりしました。
特殊な処理をしようとすると、エラーが複雑になりますね。経験値は増やしていきたいです。