Versatile modify - gkresic/commons-fields GitHub Wiki

Many times we need to persist only few object attributes which usually leads us to specialized methods, each extracting from object only attributes it should persist and then passing that attributes to specialized store logic (most commonly some specialized UPDATE SQL statement).

Using partially initialized objects we are able to implement only one modify method which updates any requested set of attributes. It is up to your preference would you send fields describing attributes to persist as separate parameter or you prefer to iterate over all object's initialized fields and update all attributes they reference.

Since updating one attribute may also alter some other (calculated, etc.) attributes, consider sending to modify also one additional parameter describing object graph this versatile modify should (re)initialize.

Look at CRUDFieldsService for one possible approach to this concept.

Validation

Often it's required to validate modified attributes before persisting them, but that validation may require access to attributes not included in ones being modified. In that case, assuming you adopted CRUDFieldsService logic, one possible approach is to:

  1. clone object describing which entity is being modified

  2. apply to that clone patch being persisted

  3. extend clone with attributes needed by validator

  4. validate that extended clone

  5. finally, after validation passes, only then proceed to persisting changes stores in patch

Something like this:

@Override
public void modify(Foo foo, Foo patch, FieldGraph<Foo.Field> graph) {

    // create mockup for validation
    Foo mockup = foo.clone();

    // apply patch to get object as it will look like after persisting
    mockup.pull(patch);

    // extend this new version with all fields needed by validator 
    mockup.extend(FooValidator.Graph, this);
    
    // validate
    FooValidator.validate(mockup);
        
    // now it's safe to persist changes stored in 'patch'
    
}
⚠️ **GitHub.com Fallback** ⚠️