Spring Data Jpa Entity RelationShip Mappings @OneToOne Bidirection (No middle table)
The relation between two entities of bidirectional kind, is emulated by the hibernate layer. Naturally only considering the possibilities of the relationship at database table Person_picture can have many relations to person. breaking the one to one relation desired. But the one to one relation is controlled at hibernate level, The same way the bidirectional relation of the one to one entities is achieved. Let do the Test to see if this is true.
Java Entities
Person Entity
@Entity
@NoArgsConstructor
@Table(name = "person", schema = "public")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO,generator = "public.person_seq")
private Long id;
private String name;
@OneToOne(mappedBy="person", cascade = CascadeType.ALL)
private PersonPicture personPicture;
public Person(String name) {
this.name = name;
}
public void addPicture(PersonPicture personPicture){
this.setPersonPicture(personPicture);
personPicture.setPerson(this);
}
public void removePicture(){
this.getPersonPicture().setPerson(null);
this.setPersonPicture(null);
}
Person_Picture Entity
@Entity
@NoArgsConstructor
@Table(name = "person_picture", schema = "public")
public class PersonPicture {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "public.person_picture_seq")
private Long id;
private String data;
@OneToOne
@JoinColumn(name = "person_id")
private Person person;
public PersonPicture(String data) {
this.data = data;
}
public void addPerson(Person person){
person.setPersonPicture(this);
this.setPerson(person);
}
public void removePerson(){
this.getPerson().setPersonPicture(null);
this.setPerson(null);
}
Hibernate creates automatically the tables the next way
Tables
create table public.person (
id int8 not null,
name varchar(255),
primary key (id)
)
create table public.person_picture (
id int8 not null,
data varchar(255),
person_id int8,
primary key (id)
)
Hibernate:
alter table if exists public.person_picture
add constraint FK2knwerrgm9a9iagkvyh7s7itp
foreign key (person_id)
references public.person
Test the behaviour
@Transactional
public void createPersonAndPicture(){
Person person1 = new Person("Jose Alberto");
PersonPicture personPicture = new PersonPicture("picture of Person ...");
person1.addPicture(personPicture);
personRepository.save(person1);
}
At the output the queries generated by hibernate on this test.
Saving Person insert also Person_Picture
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
@Transactional
public void createPictureAndPerson(){
PersonPicture personPicture = new PersonPicture("picture of Person :)");
Person _person = new Person("Jose Alberto");
personRepository.save(_person); // must save otherwise
//person must save otherwise object references an unsaved transient instance - save the transient instance before flushin
personPicture.addPerson( _person);
personPictureRepository.save(personPicture);
}
At the output the queries generated by hibernate on this test.
Saving PersonPicture require previous save Person in order to insert also Person.
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
@Transactional
public void createPersonAddPicture_checkBidirection(){
createPersonAndPicture();
Person _person = personRepository.findById(1L).get();
log.info("_person: {}", _person);
PersonPicture _personPicture = _person.getPersonPicture();
log.info("_person.getPersonPicture() is Proxy: {}", (_personPicture instanceof HibernateProxy) ? "YES" : "NO"); //YES
log.info("_person.getPersonPicture() in Initialized {}", Hibernate.isInitialized( _personPicture)); //true
log.info("_PersonPicture1: {}", _personPicture);
}
At the output the queries generated by hibernate on this test.
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
Hibernate:
select
person0_.id as id1_0_0_,
person0_.name as name2_0_0_,
personpict1_.id as id1_1_1_,
personpict1_.data as data2_1_1_,
personpict1_.person_id as person_i3_1_1_
from
public.person person0_
left outer join
public.person_picture personpict1_
on person0_.id=personpict1_.person_id
where
person0_.id=?
2022-06-21 17:01:58.435 INFO 39296 --- [ main] SpringdatajpaentityOneOneBidiApplication : _person: Person{id=1, name='Jose Alberto', personPicture=picture of Person ...}
2022-06-21 17:01:58.439 INFO 39296 --- [ main] SpringdatajpaentityOneOneBidiApplication : _person.getPersonPicture() is Proxy: NO
2022-06-21 17:01:58.439 INFO 39296 --- [ main] SpringdatajpaentityOneOneBidiApplication : _person.getPersonPicture() in Initialized true
2022-06-21 17:01:58.439 INFO 39296 --- [ main] SpringdatajpaentityOneOneBidiApplication : _PersonPicture1: PersonPicture{id=1, data='picture of Person ...', person=1 Jose Alberto}
@Transactional
public void createPictureAddPerson_checkBidirection(){
createPictureAndPerson();
PersonPicture _personPicture = personPictureRepository.findById(1L).get();
log.info("_personPicture", _personPicture);
Person _person = _personPicture.getPerson();
log.info("_personPicture.getPerson() is Proxy: {}", (_person instanceof HibernateProxy) ? "YES" : "NO");
log.info("_personPicture.getPerson() is Initialized {}", Hibernate.isInitialized( _person));
log.info("_person: {}", _person);
}
At the output the queries generated by hibernate on this test.
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
Hibernate:
select
personpict0_.id as id1_1_0_,
personpict0_.data as data2_1_0_,
personpict0_.person_id as person_i3_1_0_,
person1_.id as id1_0_1_,
person1_.name as name2_0_1_
from
public.person_picture personpict0_
left outer join
public.person person1_
on personpict0_.person_id=person1_.id
where
personpict0_.id=?
2022-06-21 17:04:08.476 INFO 36456 --- [ main] SpringdatajpaentityOneOneBidiApplication : _personPicture
2022-06-21 17:04:08.476 INFO 36456 --- [ main] SpringdatajpaentityOneOneBidiApplication : _personPicture.getPerson() is Proxy: NO
2022-06-21 17:04:08.476 INFO 36456 --- [ main] SpringdatajpaentityOneOneBidiApplication : _personPicture.getPerson() is Initialized true
2022-06-21 17:04:08.476 INFO 36456 --- [ main] SpringdatajpaentityOneOneBidiApplication : _person: Person{id=1, name='Jose Alberto', personPicture=picture of Person :)}
@Transactional
public void getPerson_checkPicture(){
createPersonAndPicture();
Person _person = personRepository.findById(1L).get();
PersonPicture personPicture = _person.getPersonPicture();
log.info("Person: {}", _person);
log.info("PersonPicture: {}", personPicture);
}
At the output the queries generated by hibernate on this test.
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
Hibernate:
select
person0_.id as id1_0_0_,
person0_.name as name2_0_0_,
personpict1_.id as id1_1_1_,
personpict1_.data as data2_1_1_,
personpict1_.person_id as person_i3_1_1_
from
public.person person0_
left outer join
public.person_picture personpict1_
on person0_.id=personpict1_.person_id
where
person0_.id=?
2022-06-21 17:06:35.632 INFO 44788 --- [ main] SpringdatajpaentityOneOneBidiApplication : Person: Person{id=1, name='Jose Alberto', personPicture=picture of Person ...}
2022-06-21 17:06:35.635 INFO 44788 --- [ main] SpringdatajpaentityOneOneBidiApplication : PersonPicture: PersonPicture{id=1, data='picture of Person ...', person=1 Jose Alberto}
@Transactional
public void getPicture_checkPerson(){
createPictureAndPerson();
PersonPicture _personPicture = personPictureRepository.findById(1L).get();
Person _person = _personPicture.getPerson();
log.info("PersonPicture: {}", _personPicture);
log.info("Person: {}", _person);
}
At the output the queries generated by hibernate on this test.
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
Hibernate:
select
personpict0_.id as id1_1_0_,
personpict0_.data as data2_1_0_,
personpict0_.person_id as person_i3_1_0_,
person1_.id as id1_0_1_,
person1_.name as name2_0_1_
from
public.person_picture personpict0_
left outer join
public.person person1_
on personpict0_.person_id=person1_.id
where
personpict0_.id=?
2022-06-21 17:14:37.057 INFO 24564 --- [ main] SpringdatajpaentityOneOneBidiApplication : PersonPicture: PersonPicture{id=1, data='picture of Person :)', person=1 Jose Alberto}
2022-06-21 17:14:37.060 INFO 24564 --- [ main] SpringdatajpaentityOneOneBidiApplication : Person: Person{id=1, name='Jose Alberto', personPicture=picture of Person :)}
@Transactional
public void deletePerson_checkPersonPictureAlsoDeleted(){
createPersonAndPicture();
personRepository.deleteById(1L);
log.info("person exist: {}",personRepository.existsById(1L)); // false
log.info("personPicture exist: {}", personPictureRepository.existsById(1L)); // false
}
The output to check the queries
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
Hibernate:
select
person0_.id as id1_0_0_,
person0_.name as name2_0_0_,
personpict1_.id as id1_1_1_,
personpict1_.data as data2_1_1_,
personpict1_.person_id as person_i3_1_1_
from
public.person person0_
left outer join
public.person_picture personpict1_
on person0_.id=personpict1_.person_id
where
person0_.id=?
Hibernate:
/* delete com.bext.onetoonebidirection.entity.PersonPicture */ delete
from
public.person_picture
where
id=?
Hibernate:
/* delete com.bext.onetoonebidirection.entity.Person */ delete
from
public.person
where
id=?
Hibernate:
/* select
count(*)
from
Person x
WHERE
x.id = :id */ select
count(*) as col_0_0_
from
public.person person0_
where
person0_.id=?
2022-06-21 17:22:07.341 INFO 39636 --- [ main] SpringdatajpaentityOneOneBidiApplication : person exist: false
Hibernate:
/* select
count(*)
from
PersonPicture x
WHERE
x.id = :id */ select
count(*) as col_0_0_
from
public.person_picture personpict0_
where
personpict0_.id=?
2022-06-21 17:22:07.344 INFO 39636 --- [ main] SpringdatajpaentityOneOneBidiApplication : personPicture exist: false
@Transactional
public void deletePersonPicture_checkPersonAlsoDeleted(){
createPictureAndPerson();
List<PersonPicture> all = personPictureRepository.findAll();
all.forEach( pp -> log.info("finadAll personPictures: {}",pp) );
//personRepository.deleteById(1L); // This delete Person and PersonPicture
personPictureRepository.deleteById(1L); // This don´t Delete PersonPicture
log.info("personPicture exist: {}", personPictureRepository.existsById(1L)); // true
log.info("person: {}", personRepository.existsById(1L)); // true
}
The output of queries generated
Hibernate:
select
nextval ('public.person_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.Person
*/ insert
into
public.person
(name, id)
values
(?, ?)
Hibernate:
select
nextval ('public.person_picture_seq')
Hibernate:
/* insert com.bext.onetoonebidirection.entity.PersonPicture
*/ insert
into
public.person_picture
(data, person_id, id)
values
(?, ?, ?)
Hibernate:
/* select
generatedAlias0
from
PersonPicture as generatedAlias0 */ select
personpict0_.id as id1_1_,
personpict0_.data as data2_1_,
personpict0_.person_id as person_i3_1_
from
public.person_picture personpict0_
Hibernate:
select
person0_.id as id1_0_0_,
person0_.name as name2_0_0_,
personpict1_.id as id1_1_1_,
personpict1_.data as data2_1_1_,
personpict1_.person_id as person_i3_1_1_
from
public.person person0_
left outer join
public.person_picture personpict1_
on person0_.id=personpict1_.person_id
where
person0_.id=?
Hibernate:
/* load com.bext.onetoonebidirection.entity.PersonPicture */ select
personpict0_.id as id1_1_1_,
personpict0_.data as data2_1_1_,
personpict0_.person_id as person_i3_1_1_,
person1_.id as id1_0_0_,
person1_.name as name2_0_0_
from
public.person_picture personpict0_
left outer join
public.person person1_
on personpict0_.person_id=person1_.id
where
personpict0_.person_id=?
2022-06-21 17:25:05.295 INFO 36468 --- [ main] SpringdatajpaentityOneOneBidiApplication : finadAll personPictures: PersonPicture{id=1, data='picture of Person :)', person=1 Jose Alberto}
Hibernate:
select
personpict0_.id as id1_1_0_,
personpict0_.data as data2_1_0_,
personpict0_.person_id as person_i3_1_0_,
person1_.id as id1_0_1_,
person1_.name as name2_0_1_
from
public.person_picture personpict0_
left outer join
public.person person1_
on personpict0_.person_id=person1_.id
where
personpict0_.id=?
Hibernate:
/* select
count(*)
from
PersonPicture x
WHERE
x.id = :id */ select
count(*) as col_0_0_
from
public.person_picture personpict0_
where
personpict0_.id=?
2022-06-21 17:25:05.313 INFO 36468 --- [ main] SpringdatajpaentityOneOneBidiApplication : personPicture exist: true
Hibernate:
/* select
count(*)
from
Person x
WHERE
x.id = :id */ select
count(*) as col_0_0_
from
public.person person0_
where
person0_.id=?
2022-06-21 17:25:05.315 INFO 36468 --- [ main] SpringdatajpaentityOneOneBidiApplication : person: true
============================================================
eot
No hay comentarios:
Publicar un comentario