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

Unique column fails PUT request for nested collections [DATAREST-1544]

Open
#1,902 0 comments 0 reactions 1 assignee View on GitHub

@odrotbohm is already working on this.

Since Dec 31, 2020.

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

Description

Lexanius opened DATAREST-1544 and commented

Hi, 

tanks for spring data. But now i have a bug.

I have a two Entities Station and Point. Point is a not exported embedded class in Station with a OneToMany relation. For both exists a @RepositoryRestResource Repository with the point one is exported = false. The Entity Point has a unique field name. Both Entities have exposed ids. The application use application/json as default MediaType.

If i want to update via PUT the Station and the points by removing the first element of the REST request, i get a Unique index or primary key violation for name.

E.g:
Existing data (in the database):

Station A {id: 1, points: [{id: 1, name: 'a'}, {id: 2, name: 'b'}, {id: 3, name: 'c'}]`
  • (0) Should replace with

Station A {id: 1, points: [{id: 1, name: 'a'}, {id: 2, name: 'b'}]

* (1) Should replace with ```
Station A {id: 1, points: [{id: 2, name: 'b'}, {id: 3, name: 'c'}]
``` *not work*.

(1) is transformed to ```
Station A {id: 1, points: [{id: 1, name: 'b'}, {id: 2, name: 'c'}] 
``` with 2 database executes _updates _and a _delete _ (in this order).
So that the database has the state before the _delete_: ```
Station A {id: 1, points: [{id: 1, name: 'b'}, {id: 2, name: 'c'}, {id: 3, name: 'c'}]
```. This cause the `_Unique index or primary key violation_`.

It should be ```
Station A {id: 1, points: [{id: 2, name: 'b'}, {id: 3, name: 'c'}]

I try to batch the request but this wont help, if i use patch the application thows a exception because of the id changing. I think the changing is done in the method DomainObjectReader#mergeCollections.

Removing the unique fields helps, but this is not a solution. What should i do? Is there a option to prevent the id changes?

Code-snippets:

@Entity
@JsonIgnoreProperties(value = \{"new"})
public class Station extends AbstractPersistable<Long> {

 @NotNull
 private String name;

 @JsonManagedReference("point")
 @OneToMany(mappedBy = "station", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
 @NotNull
 private List<Point> points = new ArrayList<>();

}

&mdash;

@Entity
@JsonIgnoreProperties(value = { "new" })
public class Point extends AbstractPersistable<Long>{

    @ManyToOne
    @JoinColumn(name = "STATION_ID", referencedColumnName = "ID", nullable = false, updatable = false)
    @JsonBackReference("point")
    @RestResource(exported = false)
    privateStation station;

    @NotEmpty
    @Column(unique = true)
    private String name;
}

&mdash;

@RepositoryRestResource(collectionResourceRel = "results", path = "station")
public interface StationRepository extends JpaRepository<Station, Long> {}

&mdash;

@RepositoryRestResource(exported = false, collectionResourceRel = "results", path = "point")
public interface PointRepository extends JpaRepository<Point, Long> {}

&mdash;

@Configuration
public class RestConfiguration implements RepositoryRestConfigurer {

    @Autowired
    private EntityManager entityManager;

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.setDefaultMediaType(MediaType.APPLICATION_JSON);
        config.exposeIdsFor(entityManager.getMetamodel().getEntities().stream()
            .map(Type::getJavaType)
            .toArray(Class[]::new));
    }
}

Affects: 3.3.1 (Neumann SR1)

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.