hibernate 一对一 和 N-1

Hibernate 一对一外键单向关联    

 事实上,单向1-1与N-1的实质是相同的,1-1是N-1的特例,单向1-1与N-1的映射配置也非常相似。只需要将原来的many-to-one元素增加unique="true"属性,用于表示N的一端也必须是唯一的,在N的一端增加了唯一的约束,即成为单向1-1。基于外键的单向1-1的配置将与无连接表N-1关联的many-to-one增加unique="true"属性即可。

one-to-one 不会加载字段,它告诉HIBERNATE 怎样加载其引用对象.如何加载呢,默认根据 主键加载其引用对象.如在t_person 中查到id=2,自动加载t_idCard 中id=2的对象信息. constrained="true",表明person主键是个外键,表示当前主键上存在着idCard约束,当 前主键id作为外键,参照了idCard. 

大家都知道hibernate中的one-to-one映射主要有两种策略,(1)一对一主键关联(单向和双向)。(2)一对一外键映射(单项和双向)。本文主要讲解一下,一对一外键映射中的双向问题,在此前先通过一个实例了解。

person和idCard,是一种一对一的关系,其中

t_person表

idnameidCard(unique)

1张三

2王五1

其中王五是没有idcard,这也符合现实中的,有些人是没有身份证的。

t_idCard表

idcardNo

111111111111111

实体类:

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)配置文件

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)

向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("张三"); 

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

 

结果如下:

mysql>select*fromt_person;

+----+------+---------+

|id|name|card_ID|

+----+------+---------+

|1|张三|NULL|

+----+------+---------+

1rowinset(0.00sec)

mysql>select*fromt_idcard;

Emptyset(0.00sec)

在插入数据:

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("王五"); 
//建立关联
person.setIdCard(idCard); 

session.save(person); 

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

 

数据库中的结果如下:

mysql>select*fromt_person;

+----+------+---------+

|id|name|card_ID|

+----+------+---------+

|1|张三|NULL|

|2|王五|1|

+----+------+---------+

2rowsinset(0.00sec)

mysql>select*fromt_idcard;

+----+------------+

|id|cardNo|

+----+------------+

|1|1111111111|

+----+------------+

1rowinset(0.00sec)

(4)加载数据,这样的话就可以从person的一端加载到idCard,

如下:

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

 

结果如下:

Hibernate:selectperson0_.idasid0_0_,person0_.nameasname0_0_,person0_.card_IDascard3_0_0_fromt_personperson0_whereperson0_.id=?

person.name=王五

Hibernate:selectidcard0_.idasid1_1_,idcard0_.cardNoascardNo1_1_,person1_.idasid0_0_,person1_.nameasname0_0_,person1_.card_IDascard3_0_0_fromt_idCardidcard0_leftouterjoint_personperson1_onidcard0_.id=person1_.idwhereidcard0_.id=?

person.cardNo=1111111111这样的就找到了person对应的idcard,那能不能有idCard找到person呢?

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

 

结果如下:

Hibernate:selectidcard0_.idasid1_1_,idcard0_.cardNoascardNo1_1_,person1_.idasid0_0_,person1_.nameasname0_0_,person1_.card_IDascard3_0_0_fromt_idCardidcard0_leftouterjoint_personperson1_onidcard0_.id=person1_.idwhereidcard0_.id=?

idCard.cardNo=1111111111

idCard.person.name=张三

结果对吗?

肯定不对,idCard.cardNo=1111111111这是王五的idCard,怎么查出来张三的呢?原因在于:

idCard的配置文件问题:

应该在idCard的配置文件的<one-to-onename="person"class="Person"/>

修改为<one-to-onename="person"class="Person"property-ref="idCard"/>

因为:如果不修改则idCard会根据自己的id和person中的id比较(因为one-to-one是通过id查找到的),这样是不符合要求的,因为我们t_idcard中的id和t_person中Card_ID相比较,这样的话可以通过

property-ref="idCard" 的设置找到t_person表中Card_ID和它作比较找到我们要找的数据。

相关推荐