Kity Cartman
Kity Cartman

Reputation: 896

Hibernate annotation @OnetoOne doesn't seem to restrict many to one entries in the database

Below are two classes defined to have one to one relationship with each other. So basically Person table is maintained to contain PersonDetails table's id as foreign key.

To my understanding as per one to one mapping for every entry in table Person there should be associated single entry in the PersonDetails entry and vice versa it true as well i.e., for every entry in the PersonDetails table there should be an associated single entry in the Person table.

TestPerson class below tries to associated single entry in PersonDetails table to two or more entries in the Person table and to my surprise it succeeds. This behavior seems similar to many to one mapping.

Can anyone explain to me why is it so? Or if I am missing anything?

@Entity
public class Person {

private int personId;
private String personName;

private PersonDetails personDetails;

@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;
}

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="personDetailsFK")
public PersonDetails getPersonDetails() {
    return personDetails;
}

public void setPersonDetails(PersonDetails personDetails) {
    this.personDetails = personDetails;
}

}

@Entity
public class PersonDetails {

private int personDeatilsId;

private int income;
private String job;
private int zipCode;

@Id
@GeneratedValue
public int getPersonDeatilsId() {
    return personDeatilsId;
}

public void setPersonDeatilsId(int personDeatilsId) {
    this.personDeatilsId = personDeatilsId;
}

public int getIncome() {
    return income;
}

public void setIncome(int income) {
    this.income = income;
}

public String getJob() {
    return job;
}

public void setJob(String job) {
    this.job = job;
}

public int getZipCode() {
    return zipCode;
}

public void setZipCode(int zipCode) {
    this.zipCode = zipCode;
}

}

public class TestPerson {

public static void main(String[] args) {
    AnnotationConfiguration configuration = new AnnotationConfiguration();
    configuration.addAnnotatedClass(Person.class);
    configuration.addAnnotatedClass(PersonDetails.class);
    configuration.configure();

    new SchemaExport(configuration).create(true, true);

    SessionFactory sessionFactory = configuration.buildSessionFactory();
    Session session = sessionFactory.getCurrentSession();

    session.beginTransaction();

    PersonDetails personDetails = new PersonDetails();
    personDetails.setIncome(100000);
    personDetails.setJob("Software Engineer");
    personDetails.setZipCode(560095);

    Person person = new Person();
    person.setPersonDetails(personDetails);
    person.setPersonName("Jimmi Hendrix");

    session.save(person);

    Person person2 = new Person();
    person2.setPersonDetails(personDetails);
    person2.setPersonName("Jimmi Page");

    session.save(person2);

    session.getTransaction().commit();
    sessionFactory.close();
}

}

Upvotes: 0

Views: 145

Answers (1)

JB Nizet
JB Nizet

Reputation: 691765

Hibernate won't check is another person already points to the same person details. Even if it did, the situation might change right after (since transactions execute concurrently), and such a check would thus not be effective. That's why this check must be done by the database itself, using a unique constraint on the Person.personDetailsFK column.

AFAIK, Hibernate generates such a unique constraint if you ask it to generate the database schema for you. If you don't, then make sure to create such a constraint.

Upvotes: 1

Related Questions