hibernate——一对一映射(1)

一对一映射本来以为挺简单的,但是一接触发现还是有些琢磨头的,但是理解之后,才会发现原来是挺简单的。

一对一映射关系,也有一个主表和从表的概念,例如人和身份证就是一对一的关系,如果将IdCard的主键设为Person的主键,那么Person为主表,而IdCard为从表,这样的映射关系决定了从表不能单独存在,必须依赖于一个主表。但是主表却可以单独存在,因为它不受从表的限制。并且得先有主表中的记录,才会对应的有从表中的记录。

下面举例说明:

建立Person和IdCard两个类:

package com.suo.domain;

public class Person {
	private int id;
	private String name;
	private IdCard idCard;
        
        ……//set/get方法
}
package com.suo.domain;

public class IdCard {
	private int id;
	private String No;
	private Person person;
        
        ……//set/get方法
}


然后就是两个类的映射文件:

Person.hbm.xml:
<hibernate-mapping package="com.suo.domain">
	
	<class name="Person">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<one-to-one name="idCard"/>
		<!-- 这一句作用不大,只是和idCard建立起关联,在通过主表查询从表的时候起作用-->
	</class>
	
</hibernate-mapping>

IdCard.hbm.xml:
<hibernate-mapping package="com.suo.domain">
	
	<class name="IdCard" table="id_card">
		<id name="id">
			<generator class="foreign">
				<param name="property">person</param>
			</generator>
		</id>
		<property name="No"/>
		<one-to-one name="person" constrained="true"/>
		<!-- 这一句很关键,因为这里的主键和person的主键是相同的,所以要和person建立起关联,
			这也就是为什么这个表是从表的原因。constrained是添加约束,即将主键同时设置为外键-->
	</class>
	
</hibernate-mapping>
注意这两个映射文件的最后一个属性的配置,IdCard.hbm.xml中的person属性是一定要配的,因为还要通过这个属性找到主表中对应记录的主键,将它作为自己的主键,它建立起从表和主表的关联。而Person.hbm.xml中的idCard属性却不是一定要配的,不配的话,不会影响到IdCard记录的保存,也不会影响到它本身的保存,那么它什么时候起作用呢?就在于通过主表来查询从表的信息时起作用,若是不配这个属性的话,那么就没有建立起主表到从表的关联,是不能通过主表记录查询到从表相应的记录的(即使有getIdCard()和setIdCard()方法,也不会起作用,因为hibernate是根据映射文件来起作用的,没有配置的属性,就等于没有这个属性一样)。所以可以认为我们这里配置的是一个双向的关联,主表关联到从表,从表关联到主表。

下面再来说一下添加记录时的情况:

若是单单添加Person,那么很简单,因为它不受IdCard的限制,可以单独存在,这个就不多说了。关键是添加IdCard的记录时,就有些稍微复杂了。先看一个例子(添加的方法就不贴出来了):

public static void main(String args[]){
		
		Person person=new Person();
		person.setName("suo");
		
		IdCard idCard=new IdCard();
		idCard.setPerson(person);//相当于是设定主键,因为idCard的主键是person的外键。
		idCard.setNo("130427");
		
		add(idCard);
	}
注意,这里定义了一个Person对象,一个IdCard对象,然后只执行了一个add(idCard)方法,即没有去添加person,而是直接去添加身份证记录,会报错吗???答案是不会报错的。运行之后,先看一下执行的sql语句:

Hibernate: insert into Person (name) values (?)
Hibernate: insert into id_card (No, id) values (?, ?)

可以看到执行了两个插入语句,而且第一个是插入person的,第二个才插入idCard,我们并没有调用add(person)啊,怎么会输出插入person呢?这个我也不知道其中的内部机理,看源代码完全,也不知道哪里是哪里。可能是在setPerson的时候,发现这个person对象是处于瞬时状态,并且在设置主键的时候,要用到这个person对象的主键,那么只有先添加这个person对象的记录了。


所以,我们可以得到如下的结论:

若要添加一个身份证记录,如果person表中已经存在了和这个身份证对应的记录,那么设置好属性,直接插入即可;如果person表中还没有和这个身份证对应的记录,那么一定要先添加一个和这个身份证对应的person,然后再添加身份证记录,这个是必须的,即使你没有显示的去调用add(person),add(idCard)也会分两步执行,先添加person,后添加对应的身份证记录,但是前提必须是有一个person对象,不管是脱管的还是瞬时的,一定要有,否则身份证记录得不到主键,就会报错了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值