Issue
I've encountered this problem that won't let me sleep
I have 2 entities Property and Tenant
each property can have 0..1 tenant, each tenant can have 1..N properties
// some annotations
public class Tenant {
// more fields
@OneToMany(mappedBy = "tenant", cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
private Set<Property> properties = new HashSet<>();
}
// some annotations
public class Property {
// more fields
@ManyToOne(fetch = FetchType.LAZY)
private Tenant tenant;
}
what am I trying to accomplish is when I create a new tenant, using cascading I want to attach it to an existing property
saving is done via JpaRepository.save(Tenant)
for example first I create new Property
{
// more fields
"tenant": null
}
then sometime later I decide I want to create a tenant for this property
{
// more fields
"properties": [
{
"id": 1, // property id I want to create this tenant for
"tenant": null
}
]
}
I believe I've tried every cascade type (except ALL and PERSIST, these 2 can't be used with detached entities)
How would it be possible to synchronize a newly created tenant with an already existing property?
I read about this that CascadeType.MERGE should do the trick but it does not for me
Any help is appreciated Thanks in advance
edit: all getters and setters are generated by lombok
rest resource for saving
@PostMapping
public ResponseEntity<Void> saveTenant(
@Valid @RequestBody TenantDto tenantDto, UriComponentsBuilder uriComponentsBuilder) {
log.info(tenantDto.toString());
Long id = tenantService.saveTenant(tenantDto);
URI location = uriComponentsBuilder.path("/api/tenants/{id}").buildAndExpand(id).toUri();
return ResponseEntity.created(location).build();
}
service
@Override
public Long saveTenant(TenantDto tenantDto) {
// mapstruct mapping
return tenantRepository.save(tenantMapper.toEntity(tenantDto)).getId();
}
repo
@Repository
public interface TenantRepository extends JpaRepository<Tenant, Long> {}
Solution
Cascading is when you have 2 entities, and you want both of them to be UPDATE
ed / INSERT
ed / whatever even though you did something only to one of them explicitly. Your question doesn't really relate to cascading - because you want to INSERT one entity, but UPDATE another one.
Now, you put a mappedBy
on the Tenant.properties
. This means that Property
will be the owning entity - it's responsible for saving the connection between these 2 entities.
It means that you need to retrieve Property
from DB and set Tenant
to it. Then when saving Property
you'll get your Foreign Key filled.
Answered By - Stanislav Bashkyrtsev
Answer Checked By - Senaida (JavaFixing Volunteer)