1

VisualForceトリガーのAPEXコードでアクセスしたいUserオブジェクトにいくつかのカスタムフィールドがあります。数式フィールドからアクセスすると、次のような気の利いた$User参照を使用できます。

$User.my_prop__c

APEXから、次のようにUserIdでUserオブジェクトをクエリする必要があります。

[select my_prop__c from User where id = :UserInfo.getUserId()].my_prop__c;

SOQLクエリなしでユーザープロパティを取得できるAPEXに組み込まれているものはありますか?そうでない場合は、ユーザープロパティの遅延読み込みとキャッシュを行うためのユーティリティクラスを知っている人がいるので、オーバーヘッドは最小限に抑えられます。

4

2 に答える 2

2

次のコードサンプルのようなものを使用します。シングルトンパターンを使用して、トランザクションの期間中、情報をメモリに静的に格納します。twamleyが提案した遅延読み込みに似ていますが、これははるかに単純なアプローチだと思います。

使用法1:UserUtil.CurrentUser.Email;

使用法2:ユーザーsomeUser = UserUtil.getUser(someUserId);

これにより、現在のユーザーまたはシステム内の他のユーザーの同じ情報にアクセスできるようになります。queryUsersメソッドはクエリ結果を返すだけであることに注意してください。これにより、クエリが独自のメソッドで分離されるため、クエリのフィールドの追加と削除が簡単になり、作業が簡単になります。

注:このコードを使用すると、すべてのユーザーが取り込まれることに注意してください。ほとんどの組織には数百人のユーザーがいないため、ヒープサイズは問題になりません。ただし、そうであれば、queryUsers()メソッドを変更して、アクティブなユーザーのみを返すか、他の基準に基づいてフィルターをかけることができます。

public class UserUtil {
//Protected Members
private static final UserUtil instance = new UserUtil();
private Map<Id, User> mapUsers;

//Properties
public static User CurrentUser {
    get { return getUser(UserInfo.getUserId()); }
}

//Constructor
private UserUtil() {
    mapUsers = new Map<Id, User>(queryUsers());
}

//Public Methods
public static User getUser(Id userId) {
    if (instance.mapUsers.containsKey(userId)) {
        return instance.mapUsers.get(userId);
    }
    else {
        throw new InvalidUserIdException('Unable to locate user id: ' + userId);
    }
}

//Private Methods
private List<User> queryUsers() {
    return [SELECT 
                Id
                , Name
                , UserName
                , Email
                , Alias 
            FROM 
                User];
}

//Internal Classes
public class InvalidUserIdException extends Exception {}

}

于 2012-07-11T22:49:33.747 に答える
0

私は自分のユーティリティクラスを書きました。私はまだより良いテクニックに興味があります。このユーティリティクラスの遅延読み込みは、最初のプロパティにアクセスしたときに読み込まれます。Update_Closed_Won_Opportunities__cとSet_Opportunities_to_Closed_Won__cは、Userオブジェクトのカスタムフィールドです(システム管理者にのみ表示されるため、ユーザーは権限をアップグレードできません)。

public with sharing class MyUserInfo {
    private Id userId;
    private User myUser; // Hold onto the user object once we've loaded it

    // Default constructor uses the active user id
    public MyUserInfo() {
        userId = UserInfo.getUserId();
    }

    // Secondary constructor accepts a user id as a parameter
    public MyUserInfo(Id someOtherUserId) {
        userId = someOtherUserId;       
    }

    // Only called one time when we first need it so grab all of the custom fields now
    private void LazyLoadUser() {
        System.AssertNotEquals(null, userId);
        myUser = [
            SELECT Update_Closed_Won_Opportunities__c, Set_Opportunities_To_Closed_Won__c
            FROM User 
            WHERE id = :userId
        ];
        System.AssertNotEquals(null, myUser, 'Unable to load user with id ' + userId); // could return defaults instead
    }

    // Getters (be sure to include each field in the SOQL of LazyLoadUser)
    public boolean UpdateClosedWonOpportunities { get {
        if (myUser == null) LazyLoadUser();
        return myUser.Update_Closed_Won_Opportunities__c;
    } }
    public boolean SetOpportunitiesToClosedWon { get {
        if (myUser == null) LazyLoadUser();
        return myUser.Set_Opportunities_To_Closed_Won__c;
    } }
}

これがそのクラスを利用した私のトリガーです。最初の行myUserInfo = new MyUserInfo();はSOQLを実行しません。これは、最初のカスタムgetプロパティが使用されるまで発生しません。後続の呼び出しにはSOQLは必要ありません。

trigger LockClosedOpportunity on Opportunity (before update) {
    MyUserInfo myUserInfo = new MyUserInfo();
    for (Opportunity o : trigger.old)
    {
        if (!myUserInfo.UpdateClosedWonOpportunities && o.StageName == 'Closed Won')
            trigger.newMap.get(o.Id).addError('You do not have permission to change an Opportunity after it has been set to Closed Won.');
    }
    for (Opportunity o : trigger.new)
    {
        if ( !myUserInfo.SetOpportunitiesToClosedWon && o.StageName == 'Closed Won' && trigger.oldMap.get(o.Id).StageName != 'Closed Won' )
            o.addError('You do not have permission to set an Opportunity to Closed Won.');
    }
}

数式では$Userに似ており、1つ(またはゼロ)で十分な場合は、複数のSOQL呼び出しに取り組むことを心配する必要はありません。

于 2012-07-10T21:51:24.960 に答える