hibernate一对一双向外键关联
hibernate一对一双向外键关联
一、双向关联
在单向关联的基础上,另一个Object也持有关联对象
二、场景
一夫一妻
三、R
?
CREATE TABLE `wife` (
? `id` int(11) NOT NULL AUTO_INCREMENT,
? `name` varchar(50) NOT NULL,
? PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8
?
?
?
CREATE TABLE `husband` (
? `id` int(11) NOT NULL AUTO_INCREMENT,
? `name` varchar(50) NOT NULL,
? `wifeid` int(11) DEFAULT NULL,
? PRIMARY KEY (`id`),
? KEY `fk_wife` (`wifeid`),
? CONSTRAINT `fk_wife` FOREIGN KEY (`wifeid`) REFERENCES `wife` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8
?
四、O
wife
?
?其中one-to-one是和单向外键关联不同地方
one-to-one:指定在Wife这个Object类中用于双向关联的属性husband
property-ref: 在关联对象中用于与此Object对象关联的属性
cascade: 级联
级联:
1 只有“关系标记”才有cascade属性:many-to-one,one-to-one ,any,?
set(map, bag, idbag, list, array) + one-to-many(many-to-many)
2 级联指的是当主控方执行操作时,关联对象(被动方)是否同步执行同一操作。
pojo和它的关系属性的关系就是“主控方 -- 被动方”的关系,如果关系属性是一个set,那么被动方就是set中的一个一个元素,。
比如:学校(School)有三个属性:地区(Address),校长(TheMaster)和学生(Set, 元素为Student)
执行session.delete(school)时,级联决定是否执行session.delete(Address),session.delete(theMaster),
是否对每个aStudent执行session.delete(aStudent)。
3 一个操作因级联cascade可能触发多个关联操作。前一个操作叫“主控操作”,后一个操作叫“关联操作”。
cascade属性的可选值:
all : 所有情况下均进行关联操作。
none:所有情况下均不进行关联操作。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操作。
delete:在执行delete时进行关联操作。?
具体执行什么“关联操作”是根据“主控操作”来的:
“主控操作” ? ? ? “关联操作”
session.saveOrUpdate --> session.saveOrUpdate (执行saveOrUpdate实际上会执行save或者update)
session.save ----> session.saveOrUpdate
session.udpate --> session.saveOrUpdate
session.delete --> session.delete
4 主控操作和关联操作的先后顺序是“先保存one,再保存many;先删除many,再删除one;先update主控方,再update被动方”
对于one-to-one,当其属性constrained="false"(默认值)时,它可看作one-to-many关系;
? 当其属性constrained="true"时,它可看作many-to-one关系;
对many-to-many,它可看作one-to-many。
比如:学校(School)有三个属性:地区(Address),校长(TheMaster,其constrained="false")和学生(Set, 元素为Student)?
当执行session.save(school)时,
实际的执行顺序为:session.save(Address);
session.save(school);
session.save(theMaster);
for( 对每一个student ){
session.save(aStudent);
}
当执行session.delete(school)时,
实际的执行顺序为:session.delete(theMaster);
for( 对每一个student ){
session.delete(aStudent);
}
session.delete(school);
session.delete(Address);
当执行session.update(school)时,
实际的执行顺序为:session.update(school);
session.saveOrUpdate(Address);
session.saveOrUpdate(theMaster);
for( 对每一个student ){
session.saveOrUpdate(aStudent);
}
注意:update操作因级联引发的关联操作为saveOrUpdate操作,而不是update操作。
saveOrUpdate与update的区别是:前者根据操作对象是保存了还是没有保存,而决定执行update还是save
extends: 实际中,删除学校不会删除地区,即地区的cascade一般设为false
?总结:级联(cascade)就是操作一个对象时,对它的属性(其cascade=true)也进行这个操作。一般将级联加在one一方,因为比如one方的记录改了,则在many中的关联记录也要跟着变化Husband.hbm.xml
?
??
六、测试类
?
package com.linys.model;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.junit.AfterClass;import org.junit.BeforeClass;import org.junit.Test;public class TestOne2OneUniFK {static SessionFactory sf;@BeforeClasspublic static void setUpBeforeClass() throws Exception {sf = new Configuration().configure().buildSessionFactory();}@Testpublic void testOne2OneUniFK(){Wife wife=new Wife();wife.setName("wife");Husband husband=new Husband();husband.setName("husband");husband.setWife(wife);wife.setHusband(husband);Session session=sf.openSession();Transaction ts=session.beginTransaction();//插入可以//session.save(wife);//session.save(husband);//插入可以//session.save(husband);//session.save(wife);//插入不行// session.save(husband);//插入可以,存wife的同时,存husbandsession.save(wife);ts.commit();}@AfterClasspublic static void tearDownAfterClass() throws Exception {sf.close();}}??