If i use this piece of code (CASE 1 in picture):
@Data
@Entity
public class PostOneUni {
@EmbeddedId //if @Id, class CompositeId must be annotated @Embeddable?
private CompositeId id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumns({
@JoinColumn(name = "id1"),
@JoinColumn(name = "id2")
})
private Set<PostCommentUniMany> comments = new HashSet<>();
...
}
and when execute creation of this object and add child comments, when saving to DB everything works as expected (ids on child PostCommentUniMany
are added as expected) but changes are not propagated to java code (Object @12081
in picture should have id
field updated to 2
and not null
).
In other case (CASE 2) I use this code:
@Data
@Entity
public class PostOneUni {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "post_id")
private Set<PostCommentUniMany> comments = new HashSet<>();
...
}
and as you can see from the picture, fields are also persisted to DB, and the object that was used to save state to DB is updated after save (Object @12052
is updated to reflect id
field to be 2
- as in DB).
How to update object @12081
in CASE 1 to reflect DB id?
UPDATE
After discussion below - problem was that if id
on entity is set manually to some value, Spring think it is not new entity and tries to do merging instead of persisting the entity.
One of "workarounds" is to set @Version
field on @Entity
class PostOneUni
that will track if entity is new or not.
@Version
private Integer version;
The problem is that because you have set the ID fields manually Spring Data calls a merge operation rather than persist:
See org.springframework.data.jpa.repository.support.SimpleJpaRepository
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) //checks if ID null {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
And the JPA spec notes that when
3.2.7.1 Merging Detached Entity State
• If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.
In your test code if you therefore do:
post = oneToManyService.addNewPost(post);
the identifiers are set correctly on the returned instance just as they are when you reload from the database. However, the original instances (in 'new' state) remain unchanged i.e do not have IDs set.
Where persist is called rather than merge, then the original (same) instance is returned and the identifiers will be set correctly on this instance.