Regarding the problem of two-way foreign key association one-to-one property-ref= in hibernate

Everyone knows that there are two main strategies for one-to-one mapping in hibernate, (1) one-to-one primary key association (one-way and two-way). (2) One-to-one foreign key mapping (single and two-way). This article mainly explains the two-way problem in one-to-one foreign key mapping. Before that, we first understand it through an example.
person and idCard are a one-to-one relationship, in which
t_person table
id name idCard(unique)
1 Zhang San
2 Wang Wu 1
Among them, Wang Wu does not have an ID card. This is also consistent with reality. Some people do not have ID cards.
t_idCard table
ID cardNo
1 11111111111111
Entity class: IdCard

package com.bjpowernode.hibernate;

public class IdCard {

private int id;

private String cardNo;

private Person person;

public Person getPerson() {
return person;
}

public void setPerson(Person person) {
this.person = person;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getCardNo() {
return cardNo;
}

public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}

}

Person

package com.bjpowernode.hibernate;

public class Person {

private int id;

private String name;

private IdCard idCard;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public IdCard getIdCard() {
return idCard;
}

public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
}

(3) Configuration file IdCard:

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bjpowernode.hibernate">
<class name="IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person" class="Person" />
</class>
</hibernate-mapping>

Person:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bjpowernode.hibernate">
<class name="Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" cascade="all" class="IdCard"
unique="true" column="card_ID" />
</class>
</hibernate-mapping>

(3)
Insert data into t_person: 
import org.hibernate.Session;

import junit.framework.TestCase;

public class One2OneTest extends TestCase {

public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();

Person person = new Person();
person.setName("Zhang San");

session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
} 

The result is as follows:

mysql> select * from t_person; 

+ —- + —— + ——— +
| id | name | card_ID |
+ —- + —— + ——— +
| 1 | Zhang San | NULL |
+ —- + —— + ——— +
1 row in set (0.00 sec)

mysql> select * from t_idcard; 

Empty set (0.00 sec) inserting data:

public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();

IdCard idCard = new IdCard();
idCard.setCardNo("1111111111");
session.save(idCard);

Person person = new Person();
person.setName("王五");
//Establish association
person.setIdCard(idCard);

session.save(person);

session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
} 

The results in the database are as follows:

mysql> select * from t_person; 

+ —- + —— + ——— +
| id | name | card_ID |
+ —- + —— + ——— +
| 1 | Zhang San | NULL |
| 2 | Wang Wu | 1 |
+ —- + —— + ——— +
2 rows in set (0.00 sec)

mysql> select * from t_idcard; 

+ —- + ———— +
| id | cardNo |
+ —- + ———— +
| 1 | 1111111111 |
+ —- + ———— +
1 row in set (0.00 sec) (4) Load data, so that it can be loaded from the person side to idCard,
as follows:

public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Person person = (Person)session.load(Person.class, 2);
System.out.println("person.name=" + person.getName());
System.out.println("person.cardNo=" + person.getIdCard().getCardNo());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
} 

The result is as follows:
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_, person0_.card_ID as card3_0_0_ from t_person person0_ where person0_.id=?
person.name=王五
Hibernate: select idcard0_.id as id1_1_, idcard0_.cardNo as cardNo1_1_, person1_.id as id0_0_, person1_.name as name0_0_, person1_.card_ID as card3_0_0_ from t_idCard idcard0_ left outer join t_person person1_ on idcard0_.id=person1_.id where idcard0_ .id=?
person.cardNo=1111111111

In this way, the idcard corresponding to the person is found. Can the person be found using the idCard?

public void testLoad2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//
IdCard idCard = (IdCard)session.load(IdCard.class, 1);
System.out.println("idCard.cardNo=" + idCard.getCardNo());
System.out.println("idCard.person.name=" + idCard.getPerson().getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
} 

The result is as follows:
Hibernate: select idcard0_.id as id1_1_, idcard0_.cardNo as cardNo1_1_, person1_.id as id0_0_, person1_.name as name0_0_, person1_.card_ID as card3_0_0_ from t_idCard idcard0_ left outer join t_person person1_ on idcard0_.id=person1_.id where idcard0_ .id=?
idCard.cardNo=1111111111
idCard.person.name=Zhang San
Is the result correct?
It’s definitely wrong. idCard.cardNo=1111111111 This is Wang Wu’s idCard. How to find out Zhang San’s? the reason is:
idCard configuration file problem:
It should be in the of the idCard configuration file
Modify to
Because: if it is not modified, the idCard will compare its own id with the id in person (because one-to-one is found by id), which does not meet the requirements, because the id in our t_idcard and the Card_ID in t_person By comparison, this would pass
The setting of property-ref=”idCard” finds the Card_ID in the t_person table and compares it to find the data we are looking for.

Summary:

property-ref: Specifies the property name of the associated class. This property will correspond to the primary key of this class. If not specified, the primary key of the other party’s associated class will be used.

Property-ref is not the field name in the database table, but the attribute name in the defined java class. Be sure to pay attention.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Algorithm skill tree Home page Overview 53417 people are learning the system