spring-projects / spring-projects/spring-data-rest

Can't update OneToMany associations (wrong merge of collections during PUT) [DATAREST-1100]

Open
#1,463 2 comments 0 reactions 1 assignee View on GitHub

@odrotbohm is already working on this.

Since Dec 31, 2020.

in: repository type: bug
Dominant language
Java
Stars
958
Forks
568
PR merge metrics
No merged PRs in 30d

Description

Andrei Kazakou opened DATAREST-1100 and commented

Steps to reproduce:

  1. enviroment: Spring Boot Data REST Starter: '1.5.1.RELEASE',spring-data-rest-webmvc: 2.6.0

  2. Create entity with the following relation:
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "RELATION_ID", insertable = false, updatable = false, nullable = false)

  3. Create PagingAndSortingRepository for the entity, relation doesn't have a repository

  4. Send POST request to create a new entity:
    {
    "entityField": 1,
    "relation": [{
    "relationId": 1,
    "relationValue": 1
    },
    {
    "relationId": 2,
    "relationValue": 2
    }]
    }

  5. Send PUT request to update the entity (delete relation item with 'Id' : 2 and add relation item with 'Id' : 3):
    {
    "entityField": 1,
    "id": 1,
    "relation": [{
    "relationId": 1,
    "relationValue": 1
    },
    {
    "relationId": 3,
    "relationValue": 3
    }]
    }

  6. Read entity with GET (to see what is the current state of the entity)
    expected: {
    "entityField": 1,
    "id": 1,
    "relation": [{
    "relationId": 1,
    "relationValue": 1
    },
    {
    "relationId": 3,
    "relationValue": 3
    }]
    }
    actual:
    {
    "entityField": 1,
    "relation": [{
    "relationId": 1,
    "relationValue": 1
    },
    {
    "relationId": 2,
    "relationValue": 2
    }]
    }

I see that the issue could be in ...webmvc.json.DomainObjectReader class
in mergeCollections(PersistentProperty<?> property, Object source, Object target,
ObjectMapper mapper) method.
It iterates source and merges elements:

while (sourceIterator.hasNext()) {

		Object sourceElement = sourceIterator.next();
		Object targetElement = targetIterator.hasNext() ? targetIterator.next() : null;

		result.add(mergeForPut(sourceElement, targetElement, mapper));
	}

and it doesn't take into account primary keys, so can be a situation when sourceElement and targetElement are different entities, so it tries to merges 2 different entities.


Affects: 2.6.4 (Ingalls SR4)

Attachments:

4 votes, 5 watchers

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.