Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only delete those referenced entities that are no longer present in an aggregate. Use an upsert for all others [DATAJDBC-224] #450

Open
spring-projects-issues opened this issue Jun 12, 2018 · 4 comments
Assignees
Labels
in: jdbc Spring Data JDBC type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link

spring-projects-issues commented Jun 12, 2018

When updating an aggregate we should not delete all referenced entities in the database.
Instead we should only delete those no longer present in the database and use an upsert/merge on the others.

There are a couple of things to watch out for.

  1. Support for upsert/merge statements varies among databases. We might need a fallback.
  2. entities might have composite ids, in which case a simple in ( ... ) might not work. We need to figure out how we might construct an equivalent statement for the supported databases.
  3. Databases and drivers will have various limits for length of SQL statements. We should at least know about these and take them into consideration.

This is a subtask of #437

Jens Schauder opened this as DATAJDBC-224

@spring-projects-issues
Copy link
Author

Tyler K Van Gorder commented

I have implemented this is a past life by: 

 

  1. Insert/Update Aggregate
  2. Insert/Update Referenced Entities (using the current, in-memory list)
  3. Delete orphans where the referenced entity's parent key is aggregate ID and reference entity's ID is not in the list of IDs from the current in-memory list)

There is one "gotcha" with step 3: If the list of referenced entities is above a certain threshold (and its database dependent) then your in-clause will have too many values. I remember Oracle complaining when the number of values exceeded 1000.

You can work around this by ordering the list of in-memory Ids, using a batch size (say 100 elements?) and bounding your delete by the first and last values of each batch:

DELETE FROM <CHILD TABLE>
WHERE
PARENT_ID = :AGGREGATE_ID AND
CHILD_ID NOT in (:id1, :id2, ......:id_last) AND
CHILD_ID BETWEEN :id1 AND :id_last

This works if your IDs are numbers...I think it would also work for IDs that were strings, so long as your ordering algorithm in Java matches that of the database

@spring-projects-issues
Copy link
Author

clgraf commented

I don't know if is it ok to ask this question here, but I really don't understand yet how the process works... this issue is really important to my project and I realized it is on the sprint right now... so It would be released soon?

@spring-projects-issues
Copy link
Author

Jens Schauder commented

Hi clgraf, sorry the sprint information was misleading. For Neumann we are busy with some changes that will break some API (nothing to drastic, but still). Since the changes break the API they must all go into Neumann and this issue isn't one of it, so it is more likely to come in Neumann+1

@spring-projects-issues spring-projects-issues added the type: enhancement A general enhancement label Dec 31, 2020
mp911de added a commit that referenced this issue Feb 21, 2022
…persistence constructor.

We now support the use of @value in persistence constructors to compute values for constructor creation.

class MyDomainObject {

	public MyDomainObject(long id, @value("#root.my_column") String my_column, @value("5+2") int computed) {
		// …
	}
}
mp911de added a commit that referenced this issue Feb 21, 2022
Document version annotation.
@Husan
Copy link

Husan commented Nov 16, 2022

Tyler K Van Gorder commented

I have implemented this is a past life by: 

 

  1. Insert/Update Aggregate
  2. Insert/Update Referenced Entities (using the current, in-memory list)
  3. Delete orphans where the referenced entity's parent key is aggregate ID and reference entity's ID is not in the list of IDs from the current in-memory list)

There is one "gotcha" with step 3: If the list of referenced entities is above a certain threshold (and its database dependent) then your in-clause will have too many values. I remember Oracle complaining when the number of values exceeded 1000.

You can work around this by ordering the list of in-memory Ids, using a batch size (say 100 elements?) and bounding your delete by the first and last values of each batch:

DELETE FROM <CHILD TABLE>
WHERE
PARENT_ID = :AGGREGATE_ID AND
CHILD_ID NOT in (:id1, :id2, ......:id_last) AND
CHILD_ID BETWEEN :id1 AND :id_last

This works if your IDs are numbers...I think it would also work for IDs that were strings, so long as your ordering algorithm in Java matches that of the database

  1. Use upserts on Bs and only delete those not longer present
  2. have function or attribute carrying about change type information

I think that the 1 st option must be default behavior or may be switched on by some annotation on Aggregate Root.
2 nd option may be must be behavior when developer define which row must be updated which insert and which must be deleted. May be similar to isNew function must be changeOperation(or changeType) function in child aggregate which must be implemented from some interfays(like Persistable) and return values as "INSERT", "UPDATE", "DELETE", "NONE"(means non operation must be performent on reference collection element).
Example:

class AgregateRoot implements Persistable{
     .........
     @UpdateStrategy("UPSERT")
     Set<ChileAggregate> aggregate;
}

class ChildAggregate implements SomeInterface{
       .......
      public changeType(){
              return "UPDATE";
      }
}

@schauder schauder added status: ideal-for-contribution An issue that a contributor can help us with in: jdbc Spring Data JDBC and removed in: jdbc Spring Data JDBC labels Mar 1, 2023
@schauder schauder removed the status: ideal-for-contribution An issue that a contributor can help us with label Mar 31, 2023
@schauder schauder changed the title Only delete those referenced entities that are no longer present in an aggregate. [DATAJDBC-224] Only delete those referenced entities that are no longer present in an aggregate. Use an upsert for all others [DATAJDBC-224] Mar 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: jdbc Spring Data JDBC type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants