一对一关联关系,当需要对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(); } } }