一对一关联分为外键关联和主键关联:外键关联是指从表中存在主表的外键,这也是一种特殊的多对一关系;主键关联是指主从表的id一致
外键关联
主表:IDCard(校园卡)
从表:Student(学生)
学生类的定义和hbm文件的配置如下
1 public class Student { 2 private int id; 3 private String name; 4 //持有idcard的外键 5 private IDCard idCard; 6 }
可以看到 学生持有校园卡外键的类结构和之前多对一关系中持有年级表外键的类结构是一样的,所以配置hbm的时候也可以看成学生和校园卡是多对一关系,只是多的一方现在只有一个而已
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Student" table="student"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name" type="java.lang.String"> 12 <column name="name" length="50" /> 13 </property> 14 <many-to-one name="idCard" column="idcardid" unique="true" cascade="all"></many-to-one> 15 </class> 16 17 </hibernate-mapping>
校园卡类的定义和hbm文件的配置如下
1 public class IDCard { 2 private int id; 3 private String num; 4 private Student student; 5 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.IDCard" table="idcard"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="num"></property> 12 13 <one-to-one name="student"></one-to-one> 14 </class> 15 16 </hibernate-mapping>
测试程序
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 7 Student student = new Student(); 8 student.setName("student"); 9 10 IDCard idCard = new IDCard(); 11 idCard.setNum("109029055"); 12 13 student.setIdCard(idCard); 14 15 //student配置了级联,存储了student也会把关联的idcard存储进去 16 session.save(student); 17 // session.save(idCard); 18 19 tx.commit(); 20 session.close(); 21 22 } 23 }
结果
主键关联
学生
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Student" table="student"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name" type="java.lang.String"> 12 <column name="name" length="50" /> 13 </property> 14 <one-to-one name="idCard" cascade="all"></one-to-one> 15 </class> 16 17 </hibernate-mapping>
校园卡
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.IDCard" table="idcard"> 7 <id name="id" column="id"> 8 <generator class="foreign"> 9 <param name="property">student</param> 10 </generator> 11 </id> 12 13 <property name="num"></property> 14 15 <!-- 若constrained=true,则表明存在外键与关联表对应,且关联表中肯定存在对应的键与其对应。--> 16 <one-to-one name="student" cascade="all" constrained="true"></one-to-one> 18 </class> 19 20 </hibernate-mapping>
测试程序
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 7 Student student = new Student(); 8 student.setName("student"); 9 10 IDCard idCard = new IDCard(); 11 idCard.setNum("109029055"); 12 13 14 //必须执行此语句 15 idCard.setStudent(student); 16 17 session.save(idCard); 18 19 tx.commit(); 20 session.close(); 21 22 } 23 }
结果
constrained(one-to-one):
constrained默认值为false
constrained
只能在one-to-one
的映射中使用,(一般在主表的映射中,有外键的那个表)。如果constrained=true
,
则表明存在外键与关联表对应,并且关联表中肯定存在对应的键与其对应,
另外该选项最关键的是影响save
和delete
的先后顺序。例如增加的时候,如果constainted=true,
则会先增加关联表,然后增加本表。
删除的时候反之。
one-to-one
的单向关联中,如果constrained=false
,则会在查询时就全部取出来,用left outer join
的方式。如果constrained=true
,hibernate
即会延迟加载sql
,只把主表的查出来,等有用到关联表的再发sql
取。
one-to- one
的双向关联中,必须设置constrained=true
,要不然会有重复数据读,如2
个表user
,car
;在位false
时sql
如
下:select * from user a left outer join car b on a.id=b.id left outer join on user c on a.id=c.id where a.id=?
删除的时候最好删除从表,删除主表会先查询下主表,在联合查询下
hibernate关系映射(一对一)