[Salesforce] Data Migration Tool を使ってDeveloper Sandboxにデータ移行する

2021.06.15

Salesforceでは開発環境やステージング環境用にSandbox機能が提供されています。
しかし、Full Sandbox、またはPartial Copy Sandbox以外のタイプのSandbox(Developer Sandboxなど)では、組織のメタデータはコピーされますが、各オブジェクトのデータ(レコード)は移行されません。

当社では、Salesforceの管理・開発に関わるメンバー増にともない各自に個別の開発環境が必要になってきました。また、Partial Copy Sandboxはステージング環境として各自の修正の統合、テストを行う環境としたいため、各自はDeveloper Sandboxを使うことになります。

しかし、前述の通りDeveloper Sandboxにはレコードは移行されないため、別途レコードを移行する必要があります。

このレコード移行を行うため、次のブログにて紹介されているForce.com開発のデータ移行ツールData Migration Toolを使ってみましたので、その知見を共有できればと思います。

Open Sourcing Salesforce Intra Org Data Migrator Tool (Datafall) | Salesforce Developers Blog

インストール

コンソールから任意のディレクトリにて次のコマンドを実行します1

$ git clone git@github.com:forcedotcom/Data-Migration-Tool.git
$ cd Data-Migration-Tool
$ mvn clean install

mvn clean installは直下のdatamigrator-module/src配下に設置されている各javaファイル等をコンパイルして、datamigrator-module/target配下に配備してくれます。ですので、javaファイルなどに修正を加える場合はdatamigrator-module/src側のファイルを操作し、操作し終わったらmvn clean installを実行してdatamigrator-module/target側に反映するという手順をふむことになります。

接続情報のセットアップ

移行元組織(Source組織)と移行先組織(Target組織)への接続情報をdatamigrator-module/src/main/resources/build.propertiesに記述します。

# SOURCE
source.sfdc.login=username@salesforce.com.sourceorg
source.sfdc.password=******
source.env.endpoint=https://test.salesforce.com/services/Soap/u/44.0/

# TARGET
target.sfdc.login=username@salesforce.com.targetorg
target.sfdc.password=******
target.env.endpoint=https://test.salesforce.com/services/Soap/u/44.0/

# Optional proxy
env.proxy.host=
env.proxy.port=

target.threads.count=1

source.type=org

object.mapping.dir=/object-mappings/
data.mapping.dir=/data-mappings/

移行データのオブジェクトマッピング

Data Migration Toolはオブジェクトの構造(参照関係)を保ったままデータ移行を行うことが可能です。 json形式で構造(Mapping)を定義します。

Object JSON Mappings · forcedotcom/Data-Migration-Tool Wiki

単一オブジェクトデータ移行

SomeField__cの値がnullでない取引先(Account)を全件移行する定義は次のとおりです。

[
  {
    "parent": "Account",
    "where": "SomeField__c != null"
  }
]

whereに条件を指定することで、条件を満たしたレコードのみ移行することができます。

親子関係オブジェクトデータ移行

親子関係を保ってデータ移行する定義は次のとおりです。 children keyにて、取引先に紐作く取引先責任者(Contact)と商談(Opportunity)を定義しています。 childObjectに子として紐付けるオブジェクトのAPI参照名を指定し、parentMappedFieldに親オブジェクト(ここではAccount)への参照を持つ項目のAPI参照名を指定します。

[
  {
    "parent": "Account",
    "refresh": true,
    "unmappedFields": [
    ],
    "children": [
      {
        "parentMappedField": "AccountId",
        "childObject": "Contact",
        "where": " AccountId != null",
        "unmappedFields": [
        ],
        "sequence": 1
      },
      {
        "parentMappedField": "AccountId",
        "childObject": "Opportunity",
        "where": " AccountId != null",
        "unmappedFields": [
        ],
        "sequence": 2
      }
    ]
  }
]

この例では指定していませんが、移行から外したい項目がある場合はunmappedFieldsに外したい項目のAPI参照名を列記します。

"unmappedFields": [
  "SomeFieldA__c",
  "SomeFieldB__c"
],

親子関係入れ子オブジェクトデータ移行

親子、孫、またその子供・・・と入れ子になった階層のMappingも定義できます。

[
  {
    "parent": "Account",
    "unmappedFields": [
    ],
    "children": [
      {
        "parentMappedField": "AccountId",
        "childObject": "Contact",
        "where": " AccountId != null",
        "unmappedFields": [
        ],
        "sequence": 1
      },
      {
        "parentMappedField": "AccountId",
        "childObject": "Opportunity",
        "where": " AccountId != null",
        "unmappedFields": [
        ],
        "sequence": 2,
        "children": [
          {
            "parentMappedField": "OpportunityId",
            "childObject": "OpportunityContactRole",
            "where": " OpportunityId != null",
            "unmappedFields": [
            ],
            "sequence": 3
          }
        ]
      }
    ]
  }
]

このようにchildrenを入れ子にするだけです。

移行を実行するJavaクラスの定義、ビルド

Mappingのjsonが準備できたら移行を実行するJavaクラスを定義します。 Javaクラスはdatamigrator-module/src/main/java/migrator/module/client/ディレクトリ直下に定義します。

package migrator.module.client;

import java.util.ArrayList;
import java.util.List;

import migrator.core.sobject.MigrableObjectFactory;
import migrator.core.utils.CommandVO;

public class MigrateAccountsContactsAndOpportunities {

  public void process() {

     List<CommandVO> list = new ArrayList<CommandVO>();

     // 定義したjsonファイルのファイル名をCommandVOコンストラクタの第二引数に与える
     list.add(new CommandVO("create", "YourMapping.json"));

     MigrateAccountsContactsAndOpportunities.migrate(list);
  }

  static public void main(String[] args) {
      MigrateAccountsContactsAndOpportunities migrate = new MigrateAccountsContactsAndOpportunities();
      migrate.process();
  }
}

クラス名を処理内容に合わせて適宜ユニークなものに設定します。 また、YourMapping.jsonの箇所を定義したMappingのjson名に置き換えます。
例えば、datamigrator-module/src/main/resources/object-mappings/Some.jsonと定義したなら、Some.jsonを指定します。

また、一つのJavaクラスの中で複数のjsonの実行を指定することができます。 process()内で複数のCommandVOオブジェクトを生成するだけです。

  public void process() {

     List<CommandVO> list = new ArrayList<CommandVO>();

     // YourMapping1.jsonとYourMapping2.jsonを処理対象にする
     list.add(new CommandVO("create", "YourMapping1.json"));
     list.add(new CommandVO("create", "YourMapping2.json"));

     MigrateAccountsContactsAndOpportunities.migrate(list);
  }

CommandVOの第一引数にはcreatedeleteを指定できます。Mappingで指定された情報をもとに、各オブジェクトレコードを作成、削除する指定になります。

Javaクラスの実装も完了したら、次のコマンドでビルドします。

$ mvn clean install

移行実行

ビルドまで終わったら次のコマンドで移行を実行します。

$ mvn exec:java -Dexec.mainClass="migrator.module.client.MigrateAccountsContactsAndOpportunities" -pl datamigrator-module

-Dexec.mainClassに与えるクラス名は定義したJavaクラス名に適宜変更します。

コンソール上で処理が走り、次のように進捗が表示され、「BUILD SUCCESS」が表示されれば移行完了です。

2021-06-15 18:14:39 INFO  SfdcApiServiceImpl:430 - Opportunity Records: 10005
2021-06-15 18:14:39 INFO  SfdcApiServiceImpl:1384 - Opportunity : Thread[1] Records: 10005
2021-06-15 18:14:53 INFO  SfdcApiServiceImpl:1396 - Thread[1] Batch Records: 200
2021-06-15 18:15:08 INFO  SfdcApiServiceImpl:1396 - Thread[1] Batch Records: 400
2021-06-15 18:15:22 INFO  SfdcApiServiceImpl:1396 - Thread[1] Batch Records: 600
2021-06-15 18:15:39 INFO  SfdcApiServiceImpl:1396 - Thread[1] Batch Records: 800
:
:
2021-06-15 18:26:08 INFO  SfdcConnection:316 - Logging out...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  17:56 min
[INFO] Finished at: 2021-06-15T18:26:08+09:00
[INFO] ------------------------------------------------------------------------

まとめ

Data Migration Toolの使い方を簡単にみてきました。jsonでかなり柔軟にMappingを定義できますので、複雑な構造を持つ組織を運用されている場合でも一度jsonとJavaクラスを用意すればチームメンバーで共有して活用することができます。

あまりコンソールに慣れていないメンバーがいる場合は、コマンド一つ実行するだけで移行処理が走るスクリプトを用意するのも良いかもしれません。

参考資料


  1. mvnコマンドがインストールされていない場合は事前にインストールする必要があります。Mac環境の場合は、brew install mvnでインストール可能です。