spring-projects / spring-projects/spring-data-rest
Unique column fails PUT request for nested collections [DATAREST-1544]
@odrotbohm is already working on this.
Since Dec 31, 2020.
- 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<>();
}
—
@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;
}
—
@RepositoryRestResource(collectionResourceRel = "results", path = "station")
public interface StationRepository extends JpaRepository<Station, Long> {}
—
@RepositoryRestResource(exported = false, collectionResourceRel = "results", path = "point")
public interface PointRepository extends JpaRepository<Point, Long> {}
—
@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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.