I'm new at entity frameworks, so pardon me if this seems silly.
Consider the following json object:
{
"id": "8850a2d2-230e-8ecb-cbb8-06068df136aa",
"fiscalCode": "QHNMPN27E68F765S",
"role": {
"id": "MED",
"name": "Medico di base"
},
"enabled": true,
"name": "Alessio",
"surname": "De Padova",
"contacts": [],
"specs": [
{
"name": "Fisiatria",
"id": "FISIA"
},
{
"name": "Cardiologia",
"id": "CARD"
}
],
"account": {
"id": "5541",
"email": "[email protected]"
},
"submit": null
}
Let's assume we are sending it as a request body in order to update it in the database. It is a user which has subentities as shown here below:
@Id
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
@Column(name = "name")
@NotNull(message = "Name cannot be null")
@Size(min = 1, message = "Name is not long enough")
private String name;
@Column(name = "fiscal_code")
@NotNull(message = "Fiscal code cannot be null")
@Size(min=16, max=16, message = "Fiscal code has to be 16 chars long")
private String fiscalCode;
@Column(name = "enabled")
private Boolean enabled;
@Column(name = "surname")
@Size(min = 1, message = "Surname is not long enough")
@NotNull(message = "Surname cannot be null")
private String surname;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "account_id")
private AccountEntity account;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "role_id")
private RoleEntity role;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "user_id")
private Set<ContactEntity> contacts;
@OneToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "users_specs",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "spec_id")
)
private Set<SpecEntity> specs;
Now, here comes the problem. Whereas I want the userentity to be able to create a new account (or contact) or update an existing one (as it is happening right now), I don't want the same to happen with specs. A user can only add or remove specs, it has not the right to create new ones or change specs' properties.
What is the right way to configure this kind of behavior?
The following code shows what I would like to do using mainly the configuration:
userEntity.setSpecs(
userEntity
.getSpecs()
.stream()
.map(spec -> specSvc.get(spec.getId()))
.collect(Collectors.toSet())
);
What I am doing right there is "correcting" each spec entity that is sent by the client. By correcting, I mean preventing name (or any other kind of property) change so that the user can only add or remove specs. But cannot update them or create them. If the server receives a spec not containing an id, it will throw an error
CodePudding user response:
In general, don't let users post your Entity directly. This will lead to all kinds of different problems in the future anyway. In your example alone, it would be uncommon if a user client can set the database id. And if you ever let a user update their own account, you probably don't want them to be able to set a role.
I would create some DTO objects and either manually map or use some mapper to map these to the JPA entities.
There are some different approaches in How to properly convert domain entities to DTOs while considering scalability & testability (although this is about the opposite direction as your case), I am linking to my own answer there but there are various alternatives.
