基于主键的一对一关联
Person类和IdCard,一对一映射。
person的属性为:id,name,idCard
IdCard的属性为:id,usefulLife,person
由于身份证和人是一对一的,身份证的id和人的id可以相同。可以使得idcard的id的产生与person保持一致。主从对象通过主键关联起来。
类Person:
- 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 IdCard getIdCard() {
- return idCard;
- }
-
- public void setIdCard(IdCard idCard) {
- this.idCard = idCard;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- }
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 IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
类IdCard:
- public class IdCard {
- private int id;
- private Date usefulLife;
- private Person person;
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public Person getPerson() {
- return person;
- }
-
- public void setPerson(Person person) {
- this.person = person;
- }
-
- public Date getUsefulLife() {
- return usefulLife;
- }
-
- public void setUsefulLife(Date usefulLife) {
- this.usefulLife = usefulLife;
- }
-
- }
public class IdCard {
private int id;
private Date usefulLife;
private Person person;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Date getUsefulLife() {
return usefulLife;
}
public void setUsefulLife(Date usefulLife) {
this.usefulLife = usefulLife;
}
}
映射文件person.hbm.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="hibernatetest01">
- <class name="Person" table="t_person">
- <id name="id" >
- <generator class="native"></generator>
- </id>
- <property name="name"></property>
- <one-to-one name="idCard"/> //person和idcard是一对一映射
- </class>
- </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernatetest01">
<class name="Person" table="t_person">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<one-to-one name="idCard"/> //person和idcard是一对一映射
</class>
</hibernate-mapping>
映射文件idcard.hbm.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="hibernatetest01">
- <class name="IdCard" table="t_idcard">
- <id name="id" >
- <generator class="foreign">
- <param name="property">person</param>
- </generator>
- </id>
- <property name="usefulLife"></property>
- <one-to-one name="person" constrained="true"/> //加上约束,保证了person必须有idcard与之对应,未加时,保存person可以没有idcard
- </class>
- </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernatetest01">
<class name="IdCard" table="t_idcard">
<id name="id" >
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife"></property>
<one-to-one name="person" constrained="true"/> //加上约束,保证了person必须有idcard与之对应,未加时,保存person可以没有idcard
</class>
</hibernate-mapping>
注: 采用外键产生方式,该类有一个属性参数,需要在配置文件中指定给他,他需要知道利用什么来产生idcard的主键。在此指定person,与下面的 <one-to-one name="person"/>对应。
测试类:
- public class Main {
- public static void main(String[] args){
- add();
- }
-
- static Person add(){
- IdCard idCard = new IdCard();
- idCard.setUsefulLife(new Date());
- Person p = new Person();
- p.setName("jianchen");
- p.setIdCard(idCard);
- idCard.setPerson(p);
- Session s = null;
- Transaction tx = null;
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- s.save(p);
- s.save(idCard);
- tx.commit();
- return p;
- }
- }
public class Main {
public static void main(String[] args){
add();
}
static Person add(){
IdCard idCard = new IdCard();
idCard.setUsefulLife(new Date());
Person p = new Person();
p.setName("jianchen");
p.setIdCard(idCard);
idCard.setPerson(p);
Session s = null;
Transaction tx = null;
s = HibernateUtil.getSession();
tx = s.beginTransaction();
s.save(p);
s.save(idCard);
tx.commit();
return p;
}
}
一对一主键关联关系的检索:
- static void query(int id){
- Session s = HibernateUtil.getSession();
- Transaction tx = s.beginTransaction();
- Person p = (Person)s.get(Person.class, id);
- System.out.println(p.getIdCard().getUsefulLife());
- tx.commit();
- }
static void query(int id){
Session s = HibernateUtil.getSession();
Transaction tx = s.beginTransaction();
Person p = (Person)s.get(Person.class, id);
System.out.println(p.getIdCard().getUsefulLife());
tx.commit();
}
在主函数中调用query(1),person和idcard是主从关系。对主类进行查询,会把从类也查询出来,体现在查询使用左外连接,一次性的查询。
Hibernate: select person0_.id as id1_1_, person0_.name as name1_1_, idcard1_.id as id2_0_, idcard1_.usefulLife as usefulLife2_0_ from t_person person0_ left outer join t_idcard idcard1_ on person0_.id=idcard1_.id where person0_.id=?
2009-02-04 15:51:20.0
就是把打印的那句话注释掉,同样会一次性的查出主从类 。查询语句如下:
Hibernate: select person0_.id as id1_1_, person0_.name as name1_1_, idcard1_.id as id2_0_, idcard1_.usefulLife as usefulLife2_0_ from t_person person0_ left outer join t_idcard idcard1_ on person0_.id=idcard1_.id where person0_.id=?
如果是查询从类,
- static void query(int id){
- Session s = HibernateUtil.getSession();
- Transaction tx = s.beginTransaction();
- IdCard idCard =(IdCard) s.get(IdCard.class, id);
- System.out.println(idCard.getPerson().getName());
- tx.commit();
- }
static void query(int id){
Session s = HibernateUtil.getSession();
Transaction tx = s.beginTransaction();
IdCard idCard =(IdCard) s.get(IdCard.class, id);
System.out.println(idCard.getPerson().getName());
tx.commit();
}
对从类进行查询只会查询出从类的信息,主类被懒加载。从查询语句上看,以上代码执行了两次查询。
Hibernate: select idcard0_.id as id2_0_, idcard0_.usefulLife as usefulLife2_0_ from t_idcard idcard0_ where idcard0_.id=?
Hibernate: select person0_.id as id1_1_, person0_.name as name1_1_, idcard1_.id as id2_0_, idcard1_.usefulLife as usefulLife2_0_ from t_person person0_ left outer join t_idcard idcard1_ on person0_.id=idcard1_.id where person0_.id=?
jianchen
把后面的打印语句删掉,就只会执行上面的一次查询。
Hibernate: select idcard0_.id as id2_0_, idcard0_.usefulLife as usefulLife2_0_ from t_idcard idcard0_ where idcard0_.id=?
使用lazy属性:
修改映射文件:
- <hibernate-mapping package="hibernatetest01">
- <class name="IdCard" table="t_idcard">
- <id name="id" >
- <generator class="foreign">
- <param name="property">person</param>
- </generator>
- </id>
- <property name="usefulLife"></property>
- <one-to-one name="person" constrained="true" lazy="false"/> //加上约束,保证了person必须有idcard与之对应,未加时,保存person可以没有idcard
- </class>
- </hibernate-mapping>
<hibernate-mapping package="hibernatetest01">
<class name="IdCard" table="t_idcard">
<id name="id" >
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife"></property>
<one-to-one name="person" constrained="true" lazy="false"/> //加上约束,保证了person必须有idcard与之对应,未加时,保存person可以没有idcard
</class>
</hibernate-mapping>
分析:
lazy=”false“表明对person不进行懒加载。这样就会导致在查询从类时也会把主类进行加载。
lazy在hibernate 3.0之前只有两个值:true ,false
3.0后lazy有三个值:true,false,proxy。其中proxy是默认的方式,采用代理实现懒加载。
在以上基础上进行进一步的修改:
<one-to-one name="person" constrained="true" lazy="true" fetch="select" />
虽然配置为懒加载,但由于设置了抓取为select ,就是说在抓取idcard时,也会抓取person。这也会导致在加载从对象时即时的加载主对象。
由此可见,hibernate中的属性配置是互相制约和影响的。hibernate的难点也在此。
基于外键的一对一关联
可以描述为多对一,加uniquer=“ture”,就变为一对一关联了
对象模型不需要改变,对映射文件进行修改。
person.hbm.xml文件:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="hibernatetest01">
- <class name="Person" table="t_person">
- <id name="id" >
- <generator class="native"></generator>
- </id>
- <property name="name"></property>
- <one-to-one name="idCard" property-ref="person"/> //person通过idcard的属性person来查找属于自己的idcard
- </class>
- </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernatetest01">
<class name="Person" table="t_person">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<one-to-one name="idCard" property-ref="person"/> //person通过idcard的属性person来查找属于自己的idcard
</class>
</hibernate-mapping>
注: property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。
idcard.hbm.xml映射文件:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="hibernatetest01">
- <class name="IdCard" table="t_idcard">
- <id name="id" >
- <generator class="native"></generator>
- </id>
- <property name="usefulLife"></property>
- <many-to-one name="person" column="person_id" unique="true"/>
- </class>
- </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernatetest01">
<class name="IdCard" table="t_idcard">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="usefulLife"></property>
<many-to-one name="person" column="person_id" unique="true"/>
</class>
</hibernate-mapping>
表结构为:
从这个表结构上看,person和idcard是一对多的关系,因为idcard表有一个外键指向person表。但是在idcard的映射文件中,把外键强制设定为唯一,这样就构成了一对一映射。
<many-to-one name="person" column="person_id" unique="true"/>