Developer

.cloneメソッドの使い方【セールスフォース】

Developer
この記事は約9分で読めます。

こんにちは、アンダーソンです。
今回はSObject クラスのメソッドの一つである、
clone()についてみていこうと思います。

スポンサーリンク

引数の数と意味

cloneメソッドには4つの引数が必要になります。
全てBoolean型でそれぞれ

  • preserveId
  • isDeepClone
  • preserveReadonlyTimestamps
  • preserveAutonumber

です。といっても全く意味がわからないので、一つづつ設定したさいの動きをみていきます。

preserveId

元のオブジェクトの ID を重複で保持するか削除するかを指定します。true に設定すると、ID は重複する ID にコピーされます。デフォルトは false であるため、ID はクリアされます。

Apex 開発者ガイド

clone先にIdを重複させるかどうかです。
Idの重複っていいのかよ。。。となるんですが実際にどんなモノなのかみていきます。

Account acc = [SELECT Id FROM Account LIMIT 1];

system.debug(acc.Id);

Account a = acc.clone(true,false,false,false);
a.Name = 'Test';

system.debug(a.Id);

insert a;

重複を〜って書いてあったので、重複が許されると思ったんですが、上記のコードですともちろんエラーで返されます。うーむ、使い所がわからない。。。基本はFalseで良さそうです。

isDeepClone

メソッドで SObject 項目の完全コピーを作成するか参照のみを作成するかを決定します。
true に設定すると、メソッドは SObject の完全コピーを作成します。リレーション項目など、SObject のすべての項目はメモリ内に複製されます。その結果、コピーした SObject の項目に変更を行っても、元の SObject は影響されません。
false に設定すると、メソッドは SObject 項目の浅いコピーを作成します。コピーされたすべてのリレーション項目は元の SObject を使用します。その結果、コピーされた SObject でリレーション項目を変更すると、元の SObject の対応する項目も変更され、元の SObject で変更するとコピーされた SObject も変更されます。デフォルトは、false です。

Apex 開発者ガイド

おそらく最もよくつかのではないでしょうか。
初めの内容と同一のレコードで、親だけ付け替えるなどのコピー機能で使った経験があります。
で普通に使っても面白くないので今回実験してみました。
今回抽出した取引先、項目が50あったんですが、それを一つづつコピーしていくやり方と、
DeepCloneでやるのとではどちらの方が処理が早いかです。

Account acc = [SELECT Id, Name,
               Type, ParentId, BillingStreet, BillingCity,
               BillingState, BillingPostalCode, BillingCountry,
               BillingLatitude, BillingLongitude, BillingGeocodeAccuracy,
               ShippingStreet, ShippingCity,
               ShippingState, ShippingPostalCode, ShippingCountry, 
               ShippingLatitude, ShippingLongitude, ShippingGeocodeAccuracy,
               Phone, Fax, AccountNumber, Website,
               Sic, Industry, AnnualRevenue, NumberOfEmployees, 
               Ownership, TickerSymbol, Description, Rating, Site, Jigsaw, 
               CleanStatus, AccountSource, DunsNumber,
               Tradestyle, NaicsCode, NaicsDesc, YearStarted, SicDesc,
               DandbCompanyId, CustomerPriority__c, SLA__c, Active__c,
               NumberofLocations__c, UpsellOpportunity__c, SLASerialNumber__c,
               SLAExpirationDate__c FROM Account LIMIT 1];

Account a = acc.clone(false,true,false,false);
/*Account a = new Account(
    Id=acc.Id,
    Name = acc.Name,
    Type = acc.Type,
    ParentId = acc.ParentId,
    BillingStreet = acc.BillingStreet,
    BillingCity = acc.BillingCity,
    BillingState = acc.BillingState ,
    BillingPostalCode = acc.BillingPostalCode ,
    BillingCountry = acc.BillingCountry,
    BillingLatitude = acc.BillingLatitude ,
    BillingLongitude = acc.BillingLongitude ,
    BillingGeocodeAccuracy = acc.BillingGeocodeAccuracy,
    ShippingStreet = acc.ShippingStreet ,
    ShippingCity = acc.ShippingCity,
    ShippingState = acc.ShippingState,
    ShippingPostalCode = acc.ShippingPostalCode ,
    ShippingCountry = acc.ShippingCountry ,
    ShippingLatitude = acc.ShippingLatitude ,
    ShippingLongitude = acc.ShippingLongitude ,
    ShippingGeocodeAccuracy = acc.ShippingGeocodeAccuracy,
    Phone = acc.Phone ,
    Fax = acc.Fax ,
    AccountNumber = acc.AccountNumber ,
    Website = acc.Website,
    Sic = acc.Sic ,
    Industry = acc.Industry ,
    AnnualRevenue = acc.AnnualRevenue ,
    NumberOfEmployees = acc.NumberOfEmployees , 
    Ownership = acc.Ownership ,
    TickerSymbol = acc.TickerSymbol ,
    Description = acc.Description ,
    Rating = acc.Rating ,
    Site = acc.Site ,
    Jigsaw = acc.Jigsaw , 
    CleanStatus = acc.CleanStatus ,
    AccountSource = acc.AccountSource ,
    DunsNumber = acc.DunsNumber,
    Tradestyle = acc.Tradestyle ,
    NaicsCode = acc.NaicsCode ,
    NaicsDesc = acc.NaicsDesc ,
    YearStarted = acc.YearStarted ,
    SicDesc = acc.SicDesc,
    DandbCompanyId = acc.DandbCompanyId ,
    CustomerPriority__c = acc.CustomerPriority__c ,
    SLA__c = acc.SLA__c ,
    Active__c = acc.Active__c,
    NumberofLocations__c = acc.NumberofLocations__c ,
    UpsellOpportunity__c = acc.UpsellOpportunity__c ,
    SLASerialNumber__c = acc.SLASerialNumber__c,
    SLAExpirationDate__c = acc.SLAExpirationDate__c
);*/

system.debug(limits.getCpuTime());

結果は。。。どちらも同じ!w
とまあ正直変わらないという結果だったんですが、コードの書く量が恐ろしく違います。
上記のコード書くのに結構な手間がかかったことを考えるとパッと同じモノを作りたいという時には間違いなくCloneを使った方がいいと思います。

preserveReadonlyTimestamps

参照のみのタイムスタンプ項目を重複で保持するか削除するかを指定します。true に設定すると、参照のみの項目 CreatedById、CreatedDate、LastModifiedById、および LastModifiedDate は重複項目にコピーされます。デフォルトは false であるため、値はクリアされます。

Apex 開発者ガイド

DeepCloneでは参照の値まで全部コピーでしたが、こちらはタイムスタンプ項目のコピーになります。全くの同じモノを作りたいとなったらこれになりますかね。
そんなタイミングあるんだろうか。。。

preserveAutonumber

元のオブジェクトの自動採番項目を複製で保持するか削除するかを指定します。true に設定すると、自動採番項目はコピーされたオブジェクトにコピーされます。デフォルトは false であるため、自動採番項目はクリアされます。

Apex 開発者ガイド

読んで字の如く自動採番項目のコピーです。
これもどう言ったタイミングで使うのを想定しているのか僕の頭では追いつかないんですが、、、

まとめ

  • Cloneには4つの引数がある
  • 全てBoolean型でそれぞれ何をコピーするかを詳細に決めることができる。

使い所によっては無茶苦茶便利なCloneメソッド。ぜひ頭に入れておきましょう。

その他の開発に関する記事はこちらです。

Developerも含めた試験問題にチャレンジしてみましょう。

コメント