一对一关联关系,当需要对2个对象进行独立对待时,分2个类来完成映射
主键关联映射,没有额外字段维护关联,id值保持一致
package org.leadfar.hibernate.model;
public class Person {
private long id;
private String name;
private IdCard idcard;
Person(){}
public long getId() {
return id;
}
public IdCard getIdcard() {
return idcard;
}
public String getName() {
return name;
}
public void setId(long id) {
this.id = id;
}
public void setIdcard(IdCard idcard) {
this.idcard = idcard;
}
public void setName(String name) {
this.name = name;
}
}
<?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="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.Person" table="t_persons" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <property name="name"/> <!-- 根据本方id到t_idcard中寻找id值相同的那条记录 --> <one-to-one name="idcard"> </one-to-one> </class> </hibernate-mapping>
package org.leadfar.hibernate.model;
public class IdCard {
private long id;
private String sn;
private Person person;
IdCard() {}
public long getId() {
return id;
}
public Person getPerson() {
return person;
}
public String getSn() {
return sn;
}
public void setId(long id) {
this.id = id;
}
public void setPerson(Person person) {
this.person = person;
}
public void setSn(String sn) {
this.sn = sn;
}
}
<?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="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.IdCard" table="t_idcard" > <id name="id"> <!-- 使用foreign表示本记录的id值依赖于对方的id值 --> <generator class="foreign"> <!-- 表示被依赖的对象(通过对象可以映射到表中某条记录,从而得到id) --> <param name="property">person</param> </generator> </id> <property name="sn" not-null="true" unique="true"></property> <!--constraint表示外键具有约束条件,即idcard存在时不能删除对应的person --> <!-- one-to-one表示根据自己的id到对方表中寻找相同id值的记录 --> <one-to-one name="person" constrained="true"></one-to-one> </class> </hibernate-mapping>
测试
package org.leadfar.hibernate.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import junit.framework.TestCase;
public class OneToOneTest extends TestCase {
public void oneToOne_save() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
/**
*配置文件映射方式:one-to-one idCard的id生成策略为foreign,参考Person的id属性来设置自己的id(两者id保存一致)
*先有Person,再有IdCard,其中IdCard的id属性生成需要参考Person中的id
*所以,必需先保存Person,再保存IdCard
*/
Person p1 = new Person();
p1.setName("张三1");
Person p2 = new Person();
p2.setName("张三2");
Person p3 = new Person();
p3.setName("张三3");
session.save(p1);
session.save(p2);
session.save(p3);
IdCard idcard = new IdCard();
idcard.setSn("21938404320997903");
idcard.setPerson(p3);//通过p3找到数据库中对应的id,然后作为idcard记录的id
session.save(idcard);
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
//根据Person获取idCard
public void oneToOne_load01() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Person p1 = (Person)session.load(Person.class, 3L);//如果id为long类型,则需要加L后缀
IdCard idcard = p1.getIdcard();
System.out.println(p1.getName()+","+idcard.getSn());
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
//根据idCard获取Person
public void oneToOne_load02() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
IdCard idcard = (IdCard)session.load(IdCard.class, 3L);
Person person = idcard.getPerson();
System.out.println(idcard.getSn()+","+person.getName());
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
唯一外键关联映射,在其中一端使用1个字段记录对方的id
package org.leadfar.hibernate.model;
public class Person {
private long id;
private String name;
private IdCard idcard;
Person(){}
public long getId() {
return id;
}
public IdCard getIdcard() {
return idcard;
}
public String getName() {
return name;
}
public void setId(long id) {
this.id = id;
}
public void setIdcard(IdCard idcard) {
this.idcard = idcard;
}
public void setName(String name) {
this.name = name;
}
}
<?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="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.Person" table="t_persons" > <!-- 外键关联时,id生成策略任意皆可,因为不是通过id进行关联的 --> <id name="id"> <generator class="assigned"> </generator> </id> <property name="name"/> <!-- property-ref="person"说明映射的时候将参考对方的person属性字段来映射,而不是通过对方的主键id来映射的!--> <!-- 如果不指定property-ref="person" 将会根据对方的id主键进行映射,就不是通过外键来映射了!一定要搞清楚!!--> <one-to-one name="idcard" property-ref="person"> </one-to-one> </class> </hibernate-mapping>
package org.leadfar.hibernate.model;
public class IdCard {
private long id;
private String sn;
private Person person;
IdCard() {}
public long getId() {
return id;
}
public Person getPerson() {
return person;
}
public String getSn() {
return sn;
}
public void setId(long id) {
this.id = id;
}
public void setPerson(Person person) {
this.person = person;
}
public void setSn(String sn) {
this.sn = sn;
}
}
<?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="org.hibernate.auction">
<class name="org.leadfar.hibernate.model.IdCard" table="t_idcard" >
<!-- 外键关联时,id生成策略任意皆可,因为不是通过id进行关联的 -->
<id name="id">
<generator class="assigned"/>
</id>
<property name="sn" not-null="true" unique="true"></property>
<!-- unique=true 将many-to-one 限制为一对一关系 -->
<!-- 外键将使用many-to-one中的属性,即person属性将作为外键被使用 -->
<!-- 也就是说,IdCard一端将通过person属性去获取Person -->
<!-- 而且,Person一端如果要使用person字段映射到本表的话,就必须使用property-ref=person -->
<!-- 这样双方才能通过唯一的person进行双向关联映射 -->
<many-to-one name="person" unique="true" column="personid"></many-to-one>
</class>
</hibernate-mapping>
测试
package org.leadfar.hibernate.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import junit.framework.TestCase;
public class OneToOneTest extends TestCase {
public void oneToOne_save() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
/**
*one-to-one 外键关联映射
*1.先保存Person (one-to-one)Idcard中的person字段值需要参考person表的主键id
*<one-to-one name="idcard" property-ref="person"> </one-to-one>
*
*2.再保存IdCard,其中IdCard中的person属性将使用前面保存的Person对象 (many-to-one)
*<many-to-one name="person" unique="true" column="personid"></many-to-one>
*/
Person p1= new Person();
p1.setId(1L);
p1.setName("1abc");
session.save(p1);
Person p2= new Person();
p2.setId(2L);
p2.setName("2abc");
session.save(p2);
Person p3= new Person();
p3.setId(3L);
p3.setName("3abc");
session.save(p3);
IdCard idcard1 = new IdCard();
idcard1.setId(2L);
idcard1.setSn("11111111111");
idcard1.setPerson(p1);//关联关系一定不要丢
session.save(idcard1);
IdCard idcard2 = new IdCard();
idcard2.setId(3L);
idcard2.setSn("22222222222");
idcard2.setPerson(p2);//关联关系一定不要丢
session.save(idcard2);
IdCard idcard3 = new IdCard();
idcard3.setId(4L);
idcard3.setSn("33333333333");
idcard3.setPerson(p3);//关联关系一定不要丢
session.save(idcard3);
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
//根据Person获取idCard
public void oneToOne_load01() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Person p1 = (Person)session.load(Person.class, 2L);//如果id为long类型,则需要加L后缀
IdCard idcard = p1.getIdcard();
System.out.println(p1.getName()+","+idcard.getSn());
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
//根据idCard获取Person
public void oneToOne_load02() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
IdCard idcard = (IdCard)session.load(IdCard.class, 2L);
Person person = idcard.getPerson();
System.out.println(idcard.getSn()+","+person.getName());
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}