I'm using spring with lombok and mapstruct and postgresSQL.
I'm facing an error on a udirectional @ManyToOne relationship on Parent / Child relationship, with my class Client
Here is my Client class :
@Getter
@Setter
@Table(name = "client")
public class Client extends AbstractEntity {
private String name;
@ManyToOne(cascade = CascadeType.ALL)
private Address address;
private boolean headOffice;
@ManyToOne(cascade= CascadeType.ALL)
@JoinColumn(name="client_parent_id")
public Client clientParent;
}
Here is my abstractEntity to generate Id and some data:
@MappedSuperclass
@Getter
@Setter
@RequiredArgsConstructor
public class AbstractEntity {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator"
)
private String id;
@CreationTimestamp
private Timestamp createdDate;
@UpdateTimestamp
private Timestamp modifiedDate;
}
Here is my client Service :
@Service
public class ClientService {
private final ClientRepository clientRepository;
private final ClientMapper clientMapper;
ClientService(ClientRepository clientRepository, ClientMapper clientMapper) {
this.clientRepository = clientRepository;
this.clientMapper = clientMapper;
}
Client getClient(String id) throws FunctionalException {
return this.clientRepository.getById(id)
.orElseThrow(
() -> new FunctionalException("Client not found")
);
}
public ClientDto createOrUpdateClient(ClientDto clientDto, String id) throws FunctionalException {
Client client;
if (id == null) {
verifyInExistence(clientDto);
client = this.clientMapper.toEntity(clientDto);
} else {
client = this.getClient(id);
this.clientMapper.updateClientFromDto(clientDto, client);
}
verifyParent(client, clientDto.getClientParentId());
return this.clientMapper.toDto(this.clientRepository.save(client));
}
private void verifyParent(Client client, String parentId) {
if (parentId != null) {
client.setClientParent(this.getClient(parentId));
} else {
client.setClientParent(null);
}
}
private void verifyInExistence(ClientDto clientDto) throws FunctionalException {
clientRepository.findByName(clientDto.getName()).ifPresent(s -> {
throw new FunctionalException(String.format("Client '%s' already exist", clientDto.getName()));
});
}
}
And my Rest Controller :
@RestController
@RequestMapping(path = "/api/client")
public class ClientResource {
private final ClientService clientService;
ClientResource(ClientService clientService) {
this.clientService = clientService;
}
@PostMapping
ClientDto addClient(@RequestBody ClientDto clientDto) throws FunctionalException {
return this.clientService.createOrUpdateClient(clientDto, null);
}
@PutMapping(path = "/{id}")
ClientDto updateClient(@PathVariable String id, @RequestBody ClientDto clientDto) throws FunctionalException {
return this.clientService.createOrUpdateClient(clientDto, id);
}
}
When i'm posting a new client with a parent or without a parent it's okay, all goes right.
But when I try to update (by using put in clientResource) in order to remove relationship between a child and parent entity I have an Hibernate Exception like this :
HibernateException: identifier of an instance of xxxx.model.Client was altered from 7fa60bf2-e176-4b96-aae4-cbfa6461cb0e to null
I read a lot of post but i'm not in the case my Id are well generated i just don't understand why i can't set null to parent to define a chil without parent. I tried also to add childrens as OneToMany but didn't understand the need to do this.
Thanks a lot for all your reponse ! :) And sorry for the bad english.