I have a requirement to deep clone (Parent -> Child -> Grand Child) records by clicking a button at the Parent Level. I believe Salesforce supports only Clone at the Parent Level, it does not have Deep Clone Out Of the Box. Has anyone ever built it ?


You could leverage the power of External Ids to join up the objects and use the sObject Clone Method. External Ids let you dynamically match the records, without having to explicitly set the ids of the parent records being created in the clone.

Let's take the example of Account -> Opportunity -> Opportunity Product

List<Account> accts = new List<Account>{};
List<Opportunity> opptys = new List<Opportunity>{};
List<OpportunityLineItem> olis = new List<OpportunityLineItem>{};

Account acc = [Select Id, Name .... from Account];

Account accNew = acc.clone(false, true); //See sObject Clone Method
accNew.ExternalId__c = acc.Name + Datetime.now(); // set unique external Id

for(Opportunity opp : [Select Id, Name, ... (Select Id, ... from OpportunityLineItems) from Opportunity where AccountId = :acc.Id]){
Opportunity newOpp = opp.clone(false, true);
newOpp.ExternalId__c = opp.Name + Datetime.now(); //set unique external id

newOpp.Account = new Account(ExternalId__c = accNew.ExternalId__c); //set parent ref


for(OpportunityLineItem oli : opp.OpportunityLineItems){

OpportunityLineItem oliNew = oli.clone(false, true);
oliNew.Opportunity = new Opportunity(ExternalId__c = newOpp.ExternalId__c); //set parent


insert accts;
upsert opptys; //upsert matches to accounts using external id
upsert olis; //upsert matches to opportunities using external id
| improve this answer | |
  • Very useful (having recently discovered the power of Externa IDs I was not aware of, such as being able to insert a parent and child(ren) all at the same time. W00t! – AMM Nov 23 '16 at 21:29

Apex: In terms of building a solution in Apex code, there is some partial support for this you can leverage. The SObject.clone method and also JSON support can help build solutions to achieve this in code, but there is no platform deep clone.

SObjectDataLoader.cls: I've recently leveraged the JSON Apex support to implement a native SObject import/export that has the same requirement. Take a look at SObjectDataLoader. Which will perform a deep serialize (and thus deserialize) of child records and related records. By combing the two operations like so you can implement a generic Apex deep clone by passing only Id's of the master records.

Set<ID> clonedMasterIds =
     SObjectDataLoader.deserialize( SObjectDataLoader.serialize(masterIdsToDeepClone) );

You can read more about this here, cloning is one of many use cases that could be applied. The serialize and deserialize methods are configurable to control what gets cloned and/or resolved during deserialization.

enter image description here

AppExchange: There is also a number of AppExchange solutions if you wanted something already pre-built.

| improve this answer | |
  • Andrew - That's indeed great work. From your blog, I came to understand that we need to pass set of Ids to serialize method. Something like this: Set<ID> clonedMasterIds = SObjectDataLoader.deserialize( SObjectDataLoader.serialize(masterIdsToDeepClone) ); However, when I do that, I get some "implementation error". Can you tell me how to fix this? Also, will it clone the master object, child and grandchild object? Any chances of hitting the governor limit???? – the_phantom May 26 '15 at 7:14
  • Thanks! It might be best to post a GitHub issue on the repo for the library, with more details on the implementation issue. But yes, it will try to reach out to child and grandhild, there are lots of chances of hitting governors with large datasets! ;-) – Andrew Fawcett May 26 '15 at 10:29

Well I guess to accomplish the same just have to maintain the order in which DML is issued. Since with every DML calls the Id field of sobject is automatically populated. You can then leverage the power of collection(which stores the reference of object rather than value) to map the child and grand child records.

Extending the *Account -> Opportunity -> Opportunity Product further.

The Util Class

class AccountDeepCloneUtil 
    public static void cloneAccount(Account acc) 
        Map<Opportunity,List<OpportunityLineItems>> OpportunityLineItemsMapping = new Map<Opportunity,List<OpportunityLineItems>>();
        List<Opportunity> newOpportunityList = new List<Opportunity>();
        List<Opportunity> oppList = [Select Id, Name, ... (Select Id, ... from OpportunityLineItems) from Opportunity where AccountId = :acc.Id];
        Account newAcc = acc.clone(false, true); //do a deep clone
        //insert the account record
        insert newAcc;
        for(Opportunity opp : oppList){
            Opportunity newOpp = opp.clone(false, true); //do a deep clone
            newOpp.Account = newAcc.Id;
        //insert opportunity
        insert newOpportunityList;

        for(Opportunity opp :OpportunityLineItemsMapping.keySet()){
            for(OpportunityLineItemoppLineItem : OpportunityLineItemsMapping.get(opp)){
                OpportunityLineItem.OpportunityId = opp.Id;

        insert OpportunityLineItemsMapping.values();

How to use the class?

AccountDeepCloneUtil.cloneAccount([Select Id, Name .... from Account WHERE Id=<your record Id>]);

PS: The code written just using a notepad. Hence may not actually compile.Please feel free to make any changes.

| improve this answer | |

Parent>Child>Grand child>Great grand child can be achieved through couple of inner classes which will be served as a storage while we iterate through and identify all levels of parent and child we wish to clone. Need to make use of Custom Settings.

| improve this answer | |
  • 1
    What needs to change in Custom Settings? Also, got any examples of this code pattern to share? – Jagular Dec 2 '14 at 14:37

I had a similar requirement and happened to see this post. I think the solutions given by @techtrekker and @Avidev9 should work but I have gone with the solution of @Avidev9 which worked fine for me. I had to clone three levels deep and was able to implement. This is entirely based on the concept of "Object Pass by Reference".

The only reason I did not go with the solution of @techtrekker is, I don't want to introduce additional external id fields.

Just thought of sharing my idea..

| improve this answer | |

Here is an app that does that. For now it clones Parent and Child, which is what most of the orgs need.

Clone any object with any related list in just 2 clicks! See this app for more info: https://appexchange.salesforce.com/listingDetail?listingId=a0N3000000B39tWEAR

| improve this answer | |
  • 1
    Looks interesting but you should provide some kind of disclaimer (whether you're related to the company behind this paid app or not, looks quite expensive). Also this doesn't answer the question 100% as the OP needs to clone grandchildren records too... – eyescream Jun 1 '13 at 23:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.