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

package com.linys.model;

/**
 * Wife entity. @author MyEclipse Persistence Tools
 */

public class Wife implements java.io.Serializable {

	// Fields

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String name;
	private Husband husband;
	// Constructors

	/** default constructor */
	public Wife() {
	}

	/** minimal constructor */
	public Wife(String name) {
		this.name = name;
	}


	// Property accessors

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Husband getHusband() {
		return husband;
	}

	public void setHusband(Husband husband) {
		this.husband = husband;
	}


}

 

 husband

 

package com.linys.model;

/**
 * Husband entity. @author MyEclipse Persistence Tools
 */

public class Husband implements java.io.Serializable {

	// Fields

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Integer id;
	private Wife wife;
	private String name;

	// Constructors

	/** default constructor */
	public Husband() {
	}

	/** minimal constructor */
	public Husband(String name) {
		this.name = name;
	}

	/** full constructor */
	public Husband(Wife wife, String name) {
		this.wife = wife;
		this.name = name;
	}

	// Property accessors

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Wife getWife() {
		return this.wife;
	}

	public void setWife(Wife wife) {
		this.wife = wife;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
 

 

五、映射文件

Wife.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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.linys.model.Wife" table="wife">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="name" length="50" not-null="true" />
        </property>
        <one-to-one name="husband" class="com.linys.model.Husband" property-ref="wife" cascade="all"/>
    </class>
</hibernate-mapping>

 

 其中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

 

<?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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.linys.model.Husband" table="husband">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="name" length="50" not-null="true" />
        </property>
        
        <many-to-one name="wife" class="com.linys.model.Wife" unique="true">
            <column name="wifeid" />
        </many-to-one>
    </class>
</hibernate-mapping>
 

 

六、测试类

 

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;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		sf = new Configuration().configure().buildSessionFactory();

	}

	@Test
	public 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的同时,存husband
		session.save(wife);
		ts.commit();
		
	}
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		sf.close();
	}

}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值