Details
-
Bug
-
Status: Closed
-
Blocker
-
Resolution: Fixed
-
V2 1.0.0, V2 1.1.0
-
None
Description
Consider the case when you want to add a new Entity (A) to a collection of that type of entities (List<A>) that belongs to another Entity(B).
A bi-directional JPA relationships, to model the case would be:
A: @ManyToOne
@JoinColumn(name = "B_ID", referencedColumnName="B_ID")
private B b;
B: @OneToMany(mappedBy = "b", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
private List<A> as;
Notice that the underlying relational model would be constrained so that B_ID in A's corresponding table is a foreign key and not null. Therefore, when inserting A rows/entities we need to make sure that B exists and provides us with a valid id.
With that setup and constraints a create request for a new A that references an existing B entity with id 3 will send something like this:
HTTP POST <path>/As
"{\"aId\":0\"b\":{\"__metadata\":
{\"uri\":\"Bs(3)\"}}}"
The problem is that the inline B entry here is interpreted as new one and olingo tries to create a new B instance out of it and persist it, instead of finding the B entity and setting as value to A's property b.
That is, after normalization with normalizeInlineEntries it becomes part of the oDataEntryProperties map that is passed to the write method with flag isCreate=true, i.e. all inside is created.
Ultimately, during em.commit this fails with :
javax.persistence.RollbackException: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: B@xxxx
(The object is new because it has been created out of the existing B because nobody bothered to call persist on it we get this exception. It's kind of misleading to the real problem here)
The client is obliged to set the referenced property 'b' or otherwise it would a) violate the underlying relational model constraints 2) there's no other way to claim to which B entity's aggregation A belongs.
So it's up to the JpaEntity implementation to consider also this case and distinguish inline requests for new entities from references to existing ones that need not be created.
For reference case, see: http://www.odata.org/documentation/odata-v2-documentation/operations/#24_Creating_new_Entries , the second create example with the entry and link.