Hibernate 、多表关联映射 - 一对一关系映射(one- to-one)


hibernate.cfg.xml:

<hibernate-configuration>
    <session-factory name="sessionFactory">
    	<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    	<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    	<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=UTF-8</property>
    	<property name="hibernate.connection.username">root</property>
    	<property name="hibernate.connection.password"></property>
    	<property name="hibernate.show_sql">true</property>
    	<property name="hibernate.format_sql">true</property>
    	<property name="hibernate.hbm2ddl.auto">update</property>
    	<mapping resource="cn/hbm/Person.hbm.xml" />
    	<mapping resource="cn/hbm/IdCard.hbm.xml" />
    </session-factory>
</hibernate-configuration>

Person:

public class Person {
	private Integer id;
	private String name;
	private IdCard idCard;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public IdCard getIdCard() {
		return idCard;
	}
	public void setIdCard(IdCard idCard) {
		this.idCard = idCard;
	}
	
}

hbm.xml

<hibernate-mapping package="cn.model">
	<class name="Person" table="PERSON">
		<id name="id" column="ID">
			<generator class="native"></generator>
		</id>
		<property name="name" column="NAME" type="java.lang.String" />
		<one-to-one name="idCard" />
	</class> 
</hibernate-mapping>

IdCard:

public class IdCard {
	private Integer id;
	private Date usefullLife;
	private Person person;
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Date getUsefullLife() {
		return usefullLife;
	}
	public void setUsefullLife(Date usefullLife) {
		this.usefullLife = usefullLife;
	}
}
hbm.xml:

<hibernate-mapping package="cn.model">
	<class name="IdCard" table="ID_CARD">
		<id name="id" column="ID">
			<!-- 对一主键关联映射的内容 foreign:表明当前表的主键的生成使用另外一个相关联的对象的标识符(依托于其他表的主键)
			和 one-to-one联合一起使用  -->
			<generator class="foreign">
				<param name="property">person</param>
			</generator>
		</id>
		<property name="usefullLife" column="USEFULL_LIFE"/>
		<!-- constrained="true" 是否添加约束  -->
		<one-to-one name="person" constrained="true" />
	</class> 
</hibernate-mapping>


创建表并添加数据

public void save(){
		Session session=null;
		Transaction tran=null;
		try{
			
			Person person=new Person();
			person.setName("杰克");
			
			IdCard idCard=new IdCard();
			idCard.setUsefullLife(new Date());
			idCard.setPerson(person);
			
			person.setIdCard(idCard);
			
			session=HibernateSessionFactory.getSession();
			tran=session.beginTransaction();
			session.save(person);
			session.save(idCard);
			tran.commit();
		}catch(Exception e){
			if(session!=null){
				session.close();
			}
		}
	}

执行后会看到,Person和IdCard的id是一样的,通过<generator class="foreign"> 外部关系的型式可以使idCard的id和person的id关联起来


再看一下创建的SQL:


他们关联的关系是使用了主外键约束进行关联;

查询的时候通过Person可以得到IdCard,通过IdCard也可以得到Person

	public Person getPersonById(Integer id){
		Session session=null;
		try{
			session=HibernateSessionFactory.getSession();
			return (Person)session.get(Person.class, id);
		}catch(Exception e){
			if(session!=null){
				session.close();
			}
		}
		return null;
	}
	public IdCard getIdCardById(Integer id){
		Session session=null;
		try{
			session=HibernateSessionFactory.getSession();
			return (IdCard)session.get(IdCard.class, id);
		}catch(Exception e){
			if(session!=null){
				session.close();
			}
		}
		return null;
	}
	
测试代码:

	@Test
	public void testGet(){
		
		Demo demo=new Demo();
		Person per=demo.getPersonById(1);
		System.out.println("人员姓名:"+per.getName()+",身份证有效期:"+per.getIdCard().getUsefullLife());
	}


	@Test
	public void testGet2(){
		Demo demo=new Demo();
		IdCard idCard=demo.getIdCardById(1);
		System.out.println("身份证ID:"+idCard.getId()+",人员姓名 :"+idCard.getPerson().getName());
	}



通过两个查询可以看出,通过IdCard获取 person的时候,实际上他们是查了两次!


对于这种一对一的映射关系,我们同样可以使用many-to-one的方式进行实现;

只需要在IdCard的映射关系中,使Person唯一即可:



只需要更改IdCard的映射文件即可:

<hibernate-mapping package="cn.model">
	<class name="IdCard" table="ID_CARD">
		<id name="id" column="ID">
			<generator class="native" />
		</id>
		<property name="usefullLife" column="USEFULL_LIFE"/>
		<many-to-one name="person" column="PERSON_ID" unique="true" not-null="true" />
	</class> 
</hibernate-mapping>

使用这种方式在创建表的时候,表之间关系和one-to-one是一样的:


但是表结构是不一样的,在IdCard表中多了一个外键的关联:



posted @ 2015-10-23 17:49  Bodi  阅读(432)  评论(0编辑  收藏  举报