0

Considering the complexities involved in JPA we are planning to use Spring Data JDBC for our entities for its simplicity. Below is the sample structure and we have up to 6 child entities. We are able to successfully insert the data into various of these entities with proper foreign key mappings.

Challenge:- We have a workflow process outside of this application that periodically updates the "requestStatus" in the "Request" entity and this is the only field that gets updated after the Request is created. As with spring data JDBC, during the update it deletes all referenced entities and recreates(inserts) it again. This is kind of a heavy operation considering 6 child entities. Are there any workaround or suggestion in terms of how to handle these scenarios

@Table("Request")
public class Request {

private String requestId; // generated in the Before Save Listener .

private String requestStatus;

@Column("requestId")
private ChildEntity1 childEntity1;

public void addChildEntity1(ChildEntity1 childEntityobj) {

   this.childEntity1 = childEntityobj;

  }

}
@Table("Child_Entity1")
public class ChildEntity1 {

    private String entity1Id; // Auto increment on DB

    private String name;

    private String SSN;

    private String requestId;

    @MappedCollection(column = "entity1Id", keyColumn = "entity2Id")
    private ArrayList<ChildEntity2> childEntity2List = new ArrayList<ChildEntity2>();

    @MappedCollection(column = "entity1Id", keyColumn = "entity3Id")
    private ArrayList<ChildEntity3> childEntity3List = new ArrayList<ChildEntity3>();

    public void addChildEntity2(ChildEntity2 childEntity2obj) {

        childEntity2List.add(childEntity2obj);
    }

    public void addChildEntity3(ChildEntity3 childEntity3obj) {

        childEntity3List.add(childEntity3obj);
    }

}
@Table("Child_Entity2")
public class ChildEntity2 {

    private String entity2Id; // Auto increment on DB

    private String partyTypeCode;
    
    private String requestId;

}
@Table(Child_Entity3)
public class ChildEntity3 {

    private String entity3Id; // Auto increment on DB

    private String PhoneCode;

    private String requestId;

}
@Test
public void createandsaveRequest() {

    Request newRequest = createRequest(); // using builder to build the object
    newRequest.addChildEntity1(createChildEntity1());
    newRequest.getChildEntity1().addChildEntity2(createChildEntity2());
    newRequest.getChildEntity1().addChildEntity3(createChildEntity3());
    requestRepository.save(newRequest);
}
dinesh
  • 13
  • 5
  • Hello All , This is my first post in SO . Do let me know if i need to provide more clarity on the question .Coming back to my question , since there is only one column that gets updated , for now i have used @Query() to fire an UPDATE query directly and this did not fire the deletes and inserts again . That said , i do want to get your feedback if this is the right approach or there are any work around . Appreciate your response . – dinesh Aug 18 '20 at 06:16

1 Answers1

0

The approach you describe in your comment:

Have a dedicated method performing exactly that update-statement is the right way to do this.

You should be aware though that this does ignore optimistic locking. So there is a risk that the following might happen

Thread/Session 1: reads an aggregate.

Thread/Session 2: updates a single field as per your question.

Thread/Session 1: writes the aggregate, possibly with other changes, overwriting the change made by Session 2.

To avoid this or similar problems you need to

  1. check that the version of the aggregate root is unchanged from when you loaded it, in order to guarantee that the method doesn't write conflicting changes.

  2. increment the version in order to guarantee that nothing else overwrites the changes made in this method.

This might mean that you need two or more SQL statements which probably means you have to fallback even more to a full custom method where you implement this, probably using an injected JdbcTemplate.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
  • 1
    Thanks for the detailed response . We will leverage the approach provided here for optimistic locking. I think it is a good trade off to have 2 or more sql statement than the overhead of the JPA as we are already using JdbcTemplate in our app for some other functionality. – dinesh Sep 16 '20 at 03:33