I'm a novice in hibernate. I was trying to create a one-to-one mapping between Person and PersonDetail entity in the following code:
@Entity
public class Person {
private int personId;
private String personName;
private PersonDetail personDetail;
@OneToOne(mappedBy="person")
public PersonDetail getPersonDetail() {
return personDetail;
}
public void setPersonDetail(PersonDetail personDetail) {
this.personDetail = personDetail;
}
@Id
@GeneratedValue
public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
}
@Entity
public class PersonDetail {
private int personDetailId;
private String zipCode;
private String job;
private double income;
private Person person;
@OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Id
@GeneratedValue
public int getPersonDetailId() {
return personDetailId;
}
public void setPersonDetailId(int personDetailId) {
this.personDetailId = personDetailId;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
}
I want that PersonDetail should be the owning entity (I know that vice versa is correct, but I just want to test). What I do not understand is the use of the mappedBy attribute which I've put in the Person entity. If I remove it, I get the following error: "Could not determine type for: com.hibernate.onetoonemapping.PersonDetail, at table: Person, for columns: [org.hibernate.mapping.Column(personDetail)]"
What does this mappedBy attribute do? I've read that mappedBy attribute is placed on the non-owning side. But what does it exactly do?
It means that that relation between entites has already been mapped, so you don't do that twice. You just say "Hey it's done over there" by using mappedBy attribute.
When you want to make a relationship bi-directional (accessible from either side of the entity) you used mappedBy
on the non-owning side because you can only define the relationship once.
mappedBy
tells Hibernate how to create instances of your entities and load the data into them. It should refer to the field name in the class that you are annotating, PersonDetail
in this instance, where the relationship is defined.
In your scenario the mappedBy attribute should not have any impact.
I was confused about the name of the primary key (it is different from "id"), but using a non-standard name as identifier (somehow as expected) does not cause the problem you are facing.
I have experimented with the mappedBy parameter in the context of OneToMany and OneToOne associations and would like to share my findings. I have a similar scenario for testing purposes and to illustrate the impact.
Person.class:
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
@Column(name = "name")
private String name;
@OneToOne
private Address address;
}
Address.class (for OneToOne tests):
@Entity
public class Address {
@Id
@GeneratedValue
private Long id;
@Column(name = "address")
private String address;
@OneToOne(mappedBy="address")
private Person person;
@OneToMany(cascade = CascadeType.ALL)
private Set<Phone> phone = new HashSet<Phone>();
}
Phone.class (for OneToMany tests):
@Entity
public class Phone {
@Id
@GeneratedValue
private Long id;
@ManyToOne(optional = false)
private Person person;
@Column(name = "number")
private String number;
}
By moving around the "mappedBy" parameter for the OneToOne association, in any case the sql statements executed by hibernate remained the same:
Hibernate:
/* insert domain.Address
*/ insert
into
Address
(id, address)
values
(default, ?)
Hibernate:
/* insert domain.Person
*/ insert
into
Person
(id, address_id, name)
values
(default, ?, ?)
For OneToMany associations I found that if you do not specify "mappedBy" hibernate automatically uses a join table, whereas with the "mappedBy" parameter the association is mapped as a seperate column in the entity table.
If I use...
@OneToMany(cascade = CascadeType.ALL)
private Set<Phone> phone = new HashSet<Phone>();
...persising a person with one phone entry results in the following statements to be executed:
Hibernate:
/* insert domain.Phone
*/ insert
into
Phone
(id, number, person_id)
values
(default, ?, ?)
Hibernate:
/* insert collection
row domain.Person.phone */ insert
into
Person_Phone
(Person_id, phone_id)
values
(?, ?)
Whereas using...
@OneToMany(mappedBy="id", cascade = CascadeType.ALL)
private Set<Phone> phone = new HashSet<Phone>();
results in a slightly different relational model that is closer to what would one possibly expect in this case:
Hibernate:
/* insert domain.Phone
*/ insert
into
Phone
(id, number, person_id)
values
(default, ?, ?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With