15

I am wondering how can I create a deep copy of a persisted object with all of its association. Let say I have the following model.

class Document {
    String title;
    String content;
    Person owner;
    Set<Citation> citations;
}

class Person {
    String name;
    Set<Document> documents;
}

class Citation {
    String title;
    Date date;
    Set<Document> documents;
}

I have a scenario in which a user might want to grab a copy of a particular document from a person and make the document his/hers then later he / she can change its content and name. In that case I can think of one way to implement that kind of scenario which is creating a deep copy of that document (with its associations).

Or maybe if anyone knows of any other possible way to do such thing without doing huge copy of data because I know it may be bad for the app performance.

I was also thinking of may be creating a reference of to the original document like having an attribute originalDocument but that way I won't be able to know which attribute (or maybe association) has been changed.

Agustinus Verdy
  • 7,267
  • 6
  • 26
  • 28

2 Answers2

7

To perform a deep copy :

public static <T> T clone(Class<T> clazz, T dtls) { 
        T clonedObject = (T) SerializationHelper.clone((Serializable) dtls); 
        return clonedObject; 
  }

This utility method will give a deep copy of the entity, and you can perform your desired things what you want to do with the cloned object.

Jayaram
  • 1,715
  • 18
  • 30
  • 3
    The problem with this one could be, It can not handle the lazy load collections and the version properties. IMHO the better way would be write the deep copy methods in each class ourselves. – RP- Oct 18 '13 at 00:14
  • can't handle lazy fields, getting failed to initialize lazy collection in the new cloned object. – coding_idiot Dec 08 '15 at 14:55
  • You can use Jackson to serialise in json in mermory it handles hibernate lazy loading (you have to configure it) – Mr_Thorynque Mar 31 '17 at 15:16
0

Jackon serialisation configuration for hibernate :

  ObjectMapper mapperInstance 
     Hibernate4Module module = new Hibernate4Module();
        module.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);

        mapperInstance.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapperInstance.disable(MapperFeature.USE_GETTERS_AS_SETTERS);
        mapperInstance.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapperInstance.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        mapperInstance.registerModule(module);

And next

clone = getMapperInstance().readValue(getMapperInstance().writeValueAsString(this));

Ok it cost some memory and cpu...

Mr_Thorynque
  • 1,749
  • 1
  • 20
  • 31