hibernate – こみなのメモ帳 / 趣味と実益のネタ帳 Wed, 20 Sep 2023 03:03:22 +0000 ja hourly 1 https://wordpress.org/?v=6.1.1 [mysql] 変数を使用したクエリの実行 /archives/1058/ /archives/1058/#respond Wed, 20 Sep 2023 03:03:22 +0000 https://www.komina.info/?p=1058 hibernateなどのORMを使ったりするとSQLを自動生成して発行してくれるので、最近ではほとんどSQLを書かないでもDBを使ったプログラムが書けるようになりました。ちょっとした結合はJPQLで済ませてしまうことも多いです。

とはいえ性能に問題があるときには生成されたSQLに向き合わないといけません。hibernateであればシステム変数hibernate.use_sql_commentstrueを設定すると生成されたSQLがログに出力されるので、これを直接DBへ投げて原因を探ることができるわけです。

吐き出されるSQLは基本的に PreparedStaetment を用いたものなので引数はすべてクエスチョンマーク ? になっています。JPQLでバインド変数を :value1 とかにしていても一律 ? に置き換わります。例えばこんな感じ。

/* from models.UserMst where loginId = :user and deletedAt is null */
select usermst0_.id as id78_, usermst0_.loginId as loginId78_, usermst0_.password as password78_, … 
from user_mst usermst0_ where usermst0_.loginId=? and (usermst0_.deletedAt is null) limit ?

これをそのままmysqlに投げると ? のところでエラーになってしまいます。そこで下記のように記述します。(?の部分を実際に引数で置換してもよいですが、定数となると実行計画が変わってしまうことがあります。)

PREPARE my_stmt FROM '
select usermst0_.id as id78_, usermst0_.loginId as loginId78_, usermst0_.password as password78_, … 
from user_mst usermst0_ where usermst0_.loginId=? and (usermst0_.deletedAt is null) limit ?'
;
SET @LoginId = 'c12345';
SET @LimitCnt = 1;
EXECUTE my_stmt USING @LoginId, @LimitCnt;

このように引数を変数として定義し、クエリ実行時に渡すことで実際のプログラム実行時と同じ条件で実行することができます。

実行計画を見たいときは select句の前に explain と記述すればよいです。テーブルを参照するのにインデックスが利用されているか、どの順番に結合されているか、などが分かります。

実行計画の詳しい読み方に付いてはここでは割愛、詳しく解説されているサイトもあるようなので。

]]>
/archives/1058/feed/ 0
hibernateのL1キャッシュを無効にする /archives/417/ /archives/417/#respond Tue, 13 Oct 2020 21:00:36 +0000 https://www.komina.info/?p=417
【注意】
この記事は過去に別サイトで執筆したものを再掲載したものです。
内容が古くなっていて現在では適用できない場合や、もっと良い方法が出来ている場合があります。
 

https://stackoverflow.com/questions/3827704/how-to-disable-hibernate-caching

このやりとりを見ると、、、

  • hibernateにはL1キャッシュとL2キャッシュがある。
  • L2キャッシュはデフォルトでOFFになっている。
  • L1キャッシュはOFFにはできない。

つまり、L1キャッシュは無効にできないということらしい。

無効にはできないが任意のオブジェクトをキャッシュから追い出すこと(セッションのevictメソッド)はできるので、リードの前に実施することでキャッシュからリードしてしまう事象は回避できそう。

    seesion.evict(yourObject);

ちなみに、L2キャッシュやクエリキャッシュについては以下のオプションが指定できる。

hibernate.cache.use.query_cache = true or false
hibernate.cache.use_second_level_cache = true or false

クエリキャッシュは単体では有効にできない。L2キャッシュを有効にした上で使用する。

]]>
/archives/417/feed/ 0