Reputation: 4029
I'm questioning myself to how could I perform that following scenario:
Let's take a sample entity Item
@Data
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Entity
class Item implements Serializable {
@Id
@GeneratedValue
@Setter(AccessLevel.NONE)
private UUID id;
private String name;
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.REFRESH})
@JoinTable(name = "item_category", joinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "category_id", referencedColumnName = "id")})
private Set<Category> categories;
@PrePersist
protected void generateUuid() {
id = UUID_GENERATOR.generate();
}
}
and Category
@Data
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Entity
class Category implements Serializable {
@Id
@GeneratedValue
@Setter(AccessLevel.NONE)
private UUID id;
private String name;
@PrePersist
protected void generateUuid() {
id = UUID_GENERATOR.generate();
}
}
In my use case, Item
should have many Category
but Item
can't directly create or update Category
, it must use existing Category
(image a drop down list of categories managed by administrator). That why Cascade.PERSIST
and Cascade.MERGE
are missing.
Now imagine following API POST /api/items
with such JSON request structure
{
"name": "new item",
"categories": [
"6d126e36-a7a5-11e7-abc4-cec278b6b50a",
"88d5a052-a7a5-11e7-abc4-cec278b6b50a"
]
}
That should create a new items with existing Category
with given ids (consider that ids are correct and exist).
However I would return response that contain complet nested entity values:
{
"name": "new item",
"categories": [
{
"id": "6d126e36-a7a5-11e7-abc4-cec278b6b50a",
"name": "CAT_A"
},
{
"id": "88d5a052-a7a5-11e7-abc4-cec278b6b50a",
"name": "CAT_B"
}
]
}
To avoid boilerplate, imagine that Dto
and DtoToEntityMapper
(and reverse) are present and working as expected.
The problem is when I will persist()
new Item
entity produces from JSON:
Item(
id=null,
name="new item",
Categories:[
Category(
id="6d126e36-a7a5-11e7-abc4-cec278b6b50a",
name=null
),
Category(
id="6d126e36-a7a5-11e7-abc4-cec278b6b50a",
name=null
)
]
)
Every below instance are detached.
Problem is after persist()
every Category
instance seems to be detached (or at least name
is still equals to null
).
So what's the best way to retrieve Category
fields?
refresh(item)
after persist(item)
?Category
instead of detached and thus fetching each Category
using id
before persist(item)
?POST
request body) and response, thus name will be pre-filled. But what's happen if id
is correct but name
is not (since I don't accept Category
update from Item
)? Simply ignore name
or raise exception?In addition if 2. is best solution, where should I fetch those nested entities? I mean in Controller
(presentation layer), in DtoToEntityMapper
(presentation layer), in Service
(service layer)
PS: Please I would stick to JPA
specification and not using Hibernate
specific features.
PS2: I would be able to do in single POST
request
Upvotes: 0
Views: 1058
Reputation: 2191
Using entityManager.merge()
instead of entityManager.persist()
should do the trick. It will return the managed instance so accessing its categories should give you the categories including the description.
Note: Be sure that you use the managed instance after the call.
Upvotes: 1