You need to sign in to do that
Don't have an account?
sihmeieos
"System.LimitException: Too many SOQL queries: 21"について
こんにちは。
ApexTriggerとApexClassを使って処理をさせている箇所で、「System.LimitException: Too many SOQL queries: 21」が発生するようになってしまいました。以前は問題なく処理できていたので、何か新しい処理が走っていると思います。原因はわからないのですが、「System.LimitException: Too many SOQL queries: 21」の内容について確認したいと思います。
[Trigger]
trigger beforeUpdateProduct on Product__c (before update) { Product__c[] p = Trigger.new; /* Call ApexClass Method */ CalculateDate.calcProductDate(p); /* Call ApexClass Method */ CreateUpdateAuto.createRental(p); }
上記のようなトリガー、つまり、Classをコールしているだけのトリガーだと、トリガーのガバナー制限(20回)にはひっかからず、Class内で100回SOQLを発行しなければ問題ないと思っていたのですが、違うのでしょうか。
テストだと正常に処理できて、画面からだとエラーになってしまうので、どこでガバナー制限にひっかかっているのか原因を特定できないのです。
テストだと、Classでは58回までSOQLをコールしているようなのですが、エラーにはなっていません。
認識に間違い、または原因に心当たりがある場合、ご指摘いただけるととても助かります。
よろしくお願いします。
どもです。
>私のガバナ制限に対する理解は上記のように考えており、これだとテストの時も画面からの操作の時も
特に変わらずに制限値にひっかからないはずです。
ここに誤解があります。
どこで実行されたかではなく、どこから呼ばれたか、です。
確認するためにSampleを作ってみました。
[Trigger]クラスをコールするだけ
[Class]Triggerから呼ばれてクエリを21回投げる(テストメソッド付き)
上記Sampleを動かすために画面からAccountを作成すると、SOQLのLimitはTrigger、Class共に20になり、21回目のクエリを投げるところでエラーになります。
ただ、テストメソッドを動かすためにrunTestしてみると、testMethod内はもちろん、Trigger、Classともに100となり、21回目のクエリも無事に投げて正常終了します。
つまり、画面から(つまりTriggerから)処理が開始されれば、その中でClassを呼んでいようが最初のTriggerが終了するまで通して20という制限になり、
testMethodから処理が開始されれば、そこから呼ばれたTrigger、Class全てを通して100になるということです。
ポイントは、どこから処理が始まったかです。
All Answers
こんにちは。
> 上記のようなトリガー、つまり、Classをコールしているだけのトリガーだと、トリガーのガバナー制限(20回)にはひっかからず、Class内で100回SOQLを発行しなければ問題ないと思っていたのですが、違うのでしょうか。
Triggerから呼ばれている以上、Triggerのガバナー制限値が適用されます。
つまりSOQLクエリ総数の制限値は、Triggerであれば20回まで。
テストメソッドでは100回までとなります。
ちなみに、Limitsを使うと各処理においてのガバナー制限値が確認できます。
上記をTriggerから呼ばれたClass内で実行すると20、テストメソッドで実行すると100が返ってくるはずです。
ikouさんこんにちは。
いつもありがとうございます。
現在、テストではガバナ制限値(100)を超えず、エラーは発生しないのですが、画面からの操作だとガバナ制限値(20)を超えてエラーが発生してしまいます。
以下のような流れでCallしています。
■テストの場合
テストクラス
↓ insert オブジェクト
Triggerコール 【ここでのSOQLコール数が20以内】
↓ Triggerから処理用のClassコール
Classでの処理 【ここでのSOQLコール数が100以内】
■画面から実行の場合
データ作成
↓
Triggerコール 【ここでのSOQLコール数が20位内】
↓ Triggerから処理用のClassコール
Classでの処理 【ここでのSOQLコール数が100位内】
私のガバナ制限に対する理解は上記のように考えており、これだとテストの時も画面からの操作の時も
特に変わらずに制限値にひっかからないはずです。
ですが、実際は、画面から実行の場合のみガバナ制限値(20)を超えたとのエラーが発生してしまいます。
何か違いがあるのでしょうか・・・。
ちなみに、教えていただいたLimitsオブジェクトを使用してみましたが、Trigger, TriggerからコースされているClass、
テストメソッド全てで100と表示されてしまいました。
どもです。
>私のガバナ制限に対する理解は上記のように考えており、これだとテストの時も画面からの操作の時も
特に変わらずに制限値にひっかからないはずです。
ここに誤解があります。
どこで実行されたかではなく、どこから呼ばれたか、です。
確認するためにSampleを作ってみました。
[Trigger]クラスをコールするだけ
[Class]Triggerから呼ばれてクエリを21回投げる(テストメソッド付き)
上記Sampleを動かすために画面からAccountを作成すると、SOQLのLimitはTrigger、Class共に20になり、21回目のクエリを投げるところでエラーになります。
ただ、テストメソッドを動かすためにrunTestしてみると、testMethod内はもちろん、Trigger、Classともに100となり、21回目のクエリも無事に投げて正常終了します。
つまり、画面から(つまりTriggerから)処理が開始されれば、その中でClassを呼んでいようが最初のTriggerが終了するまで通して20という制限になり、
testMethodから処理が開始されれば、そこから呼ばれたTrigger、Class全てを通して100になるということです。
ポイントは、どこから処理が始まったかです。
ikouさん、こんにちは。
レスが遅くなってしまい、申し訳ありません。
とてもわかりやすく解説していただき、ありがとうございました。
どうも、私はガバナ制限について明確に理解できていないようです。
■Triggerからのコール(=UIからの実行):最初のトリガーが処理終了するまでSOQLは20回までコール可能
■Classからのコール(TestMethodからの実行含む):処理が終了するまでSOQLは100回までコール可能
とりあえず、上記の理解で良いと思っていますが、当初の「200回まで」との関連がまだ良くわかりません…。
あと、ガバナ制限について、Triggerから、Classからのコールで上限値が変わるといった記述がどこにあったかも
まだ調べられていません。
ガバナ制限はForce.comでの開発では気をつけなければいけない点なので、もう少しちゃんと調べてみます。
ありがとうございました。
sihmeieos