※この記事は英語版を翻訳しており、一部機械翻訳を含むため内容は後日更新される可能性があります。最新の内容は英語版を参照してください。表示言語は画面右下の言語名から切り替えられます。
「with sharing」として宣言された Apex クラスが、トランザクションのコンテキストで SOQL クエリを実行し、条件ベースの共有ルールが実行中のユーザーと一部の行を共有する必要がある場合、クエリはこれらの行を取得できません。
これは、コミットフェーズ (Apex トランザクションが終了した直後) で、その行へのアクセスを提供する共有がデータベースに書き込まれるためです。
トリガーと実行の順序に従い、条件ベースの共有ルールは実行フローの最後で評価され、この時点でメモリに作成された共有はコミットフェーズで保存されます。Salesforce 要求の「コミット」は、レスポンスがユーザーに送信される直前に行われ、要求に対するすべての Apex 実行が終了した後に行われます。
その結果、Apexトランザクションはコミット済みデータにアクセスできないため、 SOQL クエリは同じトランザクションで評価された条件ベースの共有ルールによって共有された行を返しません。これは、Apex トランザクションはコミットされたデータにアクセスできないためです。
回避策:
サンプルシナリオ:
これは以下のステップで再現できます。
a) 以下の Apex コントローラー、Visualforce ページ、Apex トリガーを作成します。
public with sharing class AccountQueryIssue {
public String debugString { get; set; }
private Account a, b;
public AccountQueryIssue() {
debugString = '';
}
public void createAccount() {
// レコードタイプ ID を取引先のレコードタイプ ID に置き換え
a = new Account(Name = 'Acme '+ System.now(), recordTypeId='012410000002S6O');
insert a;
debugString += '<br/>Inserted account:<br/>' + JSON.serialize(a) + '<br/>';
try {
b = [SELECT Id, Name, Owner.Alias FROM Account where id = :a.Id];
} catch(Exception e) { }
if(b != null)
debugString += '<br/>Queried account:<br/>' + JSON.serialize(b) + '<br/>';
else
debugString += '<br/>Could not query account<br/>';
}
}
VF Page
<apex:page controller="AccountQueryIssue" showHeader="false" sidebar="false">
<apex:form >
<apex:commandButton action="{!createAccount}" value="Create Account"/>
</apex:form>
<apex:outputText escape="false" value="{!debugString}"/>
</apex:page>
Apex トリガ
trigger ChangeOwner on Account (before insert) {
for(Account a : Trigger.new) {
// OwnerId を CEO ロールを持つユーザーの ID に置き換え
a.OwnerId = '00541000000HJYT';
}
}
b) Apex コントローラーで取引先の作成に使用したレコードタイプである取引先レコードを、CEO より下のロールを持つユーザーと共有する基準ベースの共有ルールを作成します。
c) CEO より下のロールを持つユーザーとしてログインし、上記の Visualforce ページに移動して [Create Account (取引先の作成)] をクリックします。「Could not query account」と表示されます。ただし、実行中のユーザーは、https://<instance>.salesforce.com/<accountId> にアクセスしてアカウントに移動できます。
000382331

We use three kinds of cookies on our websites: required, functional, and advertising. You can choose whether functional and advertising cookies apply. Click on the different cookie categories to find out more about each category and to change the default settings.
Privacy Statement
Required cookies are necessary for basic website functionality. Some examples include: session cookies needed to transmit the website, authentication cookies, and security cookies.
Functional cookies enhance functions, performance, and services on the website. Some examples include: cookies used to analyze site traffic, cookies used for market research, and cookies used to display advertising that is not directed to a particular individual.
Advertising cookies track activity across websites in order to understand a viewer’s interests, and direct them specific marketing. Some examples include: cookies used for remarketing, or interest-based advertising.