Spring Data Jpa Entity RelationShip Mappings @OneToOne Unidirection Inverse
Java Entities
Capital Entity
@Entity
@NoArgsConstructor
@Table(name = "capital", schema = "public")
public class Capital {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "public.capital_seq")
private Long id;
private String name;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name="country_id_fk", referencedColumnName = "id") // this could be omitted
private Country country;
Country Entity
@Entity
@NoArgsConstructor
@Table(name = "country", schema = "public")
public class Country {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "public.country_seq")
private Long id;
private String name;
@OneToOne(mappedBy = "country", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Capital capital;
Hibernate creates automatically the tables the next way
Tables
create table public.capital (
id int8 not null,
name varchar(255),
country_id_fk int8,
primary key (id)
)
create table public.country (
id int8 not null,
name varchar(255),
primary key (id)
)
Hibernate:
alter table if exists public.capital
add constraint FK2qo7jvd6fd696h28g4xium9en
foreign key (country_id_fk)
references public.country
Test the behaviour
// Create country - capital relation and save by country
Country country = new Country();
country.setName("Mexico");
Capital capital = new Capital();
capital.setName("CDMX");
country.setCapital(capital);
capital.setCountry(country);
Country savedCountry = countryRepository.save(country);
log.info("savedCountry {} {} {}", savedCountry.getId(), savedCountry.getName(), savedCountry.getCapital().getName());
// At this moment capital has not been explicity saved, so when CountryRecovered tries to getCapital.name will fail
// IF Country-capital field OneToOne is fetch.LAZY, with fetch.EAGER saves capital immediately when country is saved.
Country countryRecovered = countryRepository.findById(savedCountry.getCapital().getId()).get();
log.info("countryRecovered: {} {} {}", countryRecovered.getId(), countryRecovered.getName(), countryRecovered.getCapital().getName());
// Saving item for sure can recover Customer indepently of fetch.LAZY
Capital savedCapital = capitalRepository.save(capital);
log.info("savedCapital: {}", savedCapital);
// Create new Customer - Item relation and save by item.
Country countryB = new Country("France");
Capital capitalB = new Capital("Paris");
capitalB.setCountry(countryB);
//capitalB.setCountry(savedCountry);
//capitalB.setCountry(country); // This will generate error: detached entity passed to persist because OneToOne violated
Capital capitalBsaved = capitalRepository.save(capitalB);
log.info("savedCapital {}", capitalBsaved);
On the output the queries generated by hibernate on the test.
Creation of tables
Hibernate:
create table public.capital (
id int8 not null,
name varchar(255),
country_id_fk int8,
primary key (id)
)
Hibernate:
create table public.country (
id int8 not null,
name varchar(255),
primary key (id)
)
Hibernate:
alter table if exists public.capital
add constraint FK2qo7jvd6fd696h28g4xium9en
foreign key (country_id_fk)
references public.country
Queries executed by test
Hibernate:
select
nextval ('public.country_seq')
Hibernate:
select
nextval ('public.capital_seq')
Hibernate:
/* insert com.bext.onetooneunidirectionInverse.entity.Country
*/ insert
into
public.country
(name, id)
values
(?, ?)
Hibernate:
/* insert com.bext.onetooneunidirectionInverse.entity.Capital
*/ insert
into
public.capital
(country_id_fk, name, id)
values
(?, ?, ?)
2022-06-20 20:27:41.206 INFO 28404 --- [ main] .o.SpringdatajpaentitymappingApplication : savedCountry 1 Mexico CDMX
Hibernate:
select
country0_.id as id1_1_0_,
country0_.name as name2_1_0_
from
public.country country0_
where
country0_.id=?
Hibernate:
/* load com.bext.onetooneunidirectionInverse.entity.Capital */ select
capital0_.id as id1_0_0_,
capital0_.country_id_fk as country_3_0_0_,
capital0_.name as name2_0_0_
from
public.capital capital0_
where
capital0_.country_id_fk=?
2022-06-20 20:27:41.219 INFO 28404 --- [ main] .o.SpringdatajpaentitymappingApplication : countryRecovered: 1 Mexico CDMX
Hibernate:
/* load com.bext.onetooneunidirectionInverse.entity.Capital */ select
capital0_.id as id1_0_1_,
capital0_.country_id_fk as country_3_0_1_,
capital0_.name as name2_0_1_,
country1_.id as id1_1_0_,
country1_.name as name2_1_0_
from
public.capital capital0_
left outer join
public.country country1_
on capital0_.country_id_fk=country1_.id
where
capital0_.id=?
Hibernate:
/* load com.bext.onetooneunidirectionInverse.entity.Capital */ select
capital0_.id as id1_0_0_,
capital0_.country_id_fk as country_3_0_0_,
capital0_.name as name2_0_0_
from
public.capital capital0_
where
capital0_.country_id_fk=?
2022-06-20 20:27:41.225 INFO 28404 --- [ main] .o.SpringdatajpaentitymappingApplication : savedCapital: Capital{id=1, name='CDMX', coutnry.name=Mexico}
Hibernate:
select
nextval ('public.capital_seq')
Hibernate:
select
nextval ('public.country_seq')
Hibernate:
/* insert com.bext.onetooneunidirectionInverse.entity.Country
*/ insert
into
public.country
(name, id)
values
(?, ?)
Hibernate:
/* insert com.bext.onetooneunidirectionInverse.entity.Capital
*/ insert
into
public.capital
(country_id_fk, name, id)
values
(?, ?, ?)
2022-06-20 20:27:41.232 INFO 28404 --- [ main] .o.SpringdatajpaentitymappingApplication : savedCapital Capital{id=2, name='Paris', coutnry.name=France}
============================================================
eot
No hay comentarios:
Publicar un comentario