Hibernate 一对一关系映射


Hibernate的一对一关系映射分成两种方式:

  • 唯一外键关联
  • 主键关联

下面分别说明两种方式的映射操作。

一、Hibernate一对一关系映射-唯一外键关联

1.1、需求分析

示例分析

  •  我们采用的示例为公民和身份证。
  •  一位公民只允许有一张身份证。
  •  而一张身份证也只能属于某一位公民。
  •  公民和身份证就是典型的一对一关系。

1.2、一对一唯一外键关联的表关系建立

唯一外键这种方式和一对多的关联非常类似,也是使用外键进行关联,但是添加了唯一约束来限制外键值,从而实现了一对一关联,如下图所示:

1.3、建立实体类关系

Person实体类:一个公民只能有一张身份证,所以在公民实体类中应该包含一个身份证的信息,代码如下

/**
 * 公民类
 * @author http://www.yiidian.com
 *
 */
public class Person implements Serializable{
	private Integer id;
	private String name;
	
	//关联身份证
	private Card card;

	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 Card getCard() {
		return card;
	}

	public void setCard(Card card) {
		this.card = card;
	}
	
	
	
}

一个身份证只能属于一个公民,所以在身份证实体类中应该包含一个公民的信息,代码如下:

/**
 * 身份证类
 * @author http://www.yiidian.com
 *
 */
public class Card implements Serializable{
	private Integer id;
	private String name;
	//关联公民
	private Person person;
	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 Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	
}

接下来的问题是如何通过配置的方式把实体之间的关系建立起来关系。

1.4、映射配置文件

公民配置Person.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping package="com.yiidian.domain">
 
 	<class name="Person" table="t_person_fk">
 		<id name="id" column="id">
 			<generator class="native"></generator>
 		</id>
 		<property name="name" column="name"></property>
 		
 		<!-- 一对一 -->
 		<one-to-one name="card" class="Card"/>
 		
 	</class>
 
</hibernate-mapping>   

身份证配置Card.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping package="com.yiidian.domain">
 
 	<class name="Card" table="t_card_fk">
 		<id name="id" column="id">
 			<generator class="native"></generator>
 		</id>
 		<property name="name" column="name"></property>
 		
 		<!-- 唯一外键(一对一) -->
 		<many-to-one name="person" class="Person"
 			column="person_id" unique="true"/>
 		
 	</class>
 
</hibernate-mapping>   

1.5、hibernate.cfg.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
	
<hibernate-configuration>	
	<!-- 连接数据库的参数 -->
<session-factory>
	<!-- 1.连接数据库参数 -->
	<property name="hibernate.connection.driver_class">
		com.mysql.jdbc.Driver
	</property>
	<property name="hibernate.connection.url">
		jdbc:mysql://localhost:3306/hibernate
	</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">root</property>

	<!-- hibernate方言 -->
	<property name="hibernate.dialect">
		org.hibernate.dialect.MySQLDialect
	</property>

	<!-- 2.hibernate扩展参数 -->
	<property name="hibernate.show_sql">true</property>
	<property name="hibernate.format_sql">true</property>
	<property name="hibernate.hbm2ddl.auto">update</property>

	<!-- *.hbm.xml文件 -->
	<mapping resource="com/yiidian/domain/Person.hbm.xml" />
	<mapping resource="com/yiidian/domain/Card.hbm.xml" />
</session-factory>
</hibernate-configuration>	

1.6、执行一对一保存保存

/**
 * 演示Hibernate的一对一关系映射操作
 * 
 * @author http://www.yiidian.com
 * 
 */
public class Demo {

	/**
	 * 添加
	 */
	@Test
	public void test1(){
		Person p = new Person();
		p.setName("小苍");
		
		Card c = new Card();
		c.setName("1001");
		
		p.setCard(c);
		c.setPerson(p);
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		session.save(p);
		session.save(c);
		
		tx.commit();
		session.close();
	}

}

1.7、运行结果

控制台显示:

Hibernate: 
    insert 
    into
        t_person_fk
        (name) 
    values
        (?)
Hibernate: 
    insert 
    into
        t_card_fk
        (name, person_id) 
    values
        (?, ?)

一共建立两张表,分别为t_person_fk,t_card_fk。

t_person_fk表数据:

t_card_fk表的数据:

 

源码下载:https://pan.baidu.com/s/1qYMEE1e

二、Hibernate一对一关系映射-主键关联

1.1、一对一主键关联的表关系建立

主键关联的方式,是在其中一张表把其主键同时设置为外键,关联对方表,如下图所示:

1.2、建立实体类关系

Person实体类:一个公民只能有一张身份证,所以在公民实体类中应该包含一个身份证的信息,代码如下

/**
 * 公民类
 * @author http://www.yiidian.com
 *
 */
public class Person implements Serializable{
	private Integer id;
	private String name;
	
	//关联身份证
	private Card card;

	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 Card getCard() {
		return card;
	}

	public void setCard(Card card) {
		this.card = card;
	}
	
	
	
}

一个身份证只能属于一个公民,所以在身份证实体类中应该包含一个公民的信息,代码如下:

/**
 * 身份证类
 * @author http://www.yiidian.com
 *
 */
public class Card implements Serializable{
	private Integer id;
	private String name;
	//关联公民
	private Person person;
	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 Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	
}

接下来的问题是如何通过配置的方式把实体之间的关系建立起来关系。

1.3、映射配置文件

公民配置Person.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping package="com.yiidian.domain">
 
 	<class name="Person" table="t_person_pk">
 		<id name="id" column="id">
 			<generator class="native"></generator>
 		</id>
 		<property name="name" column="name"></property>
 		
 		<!-- 一对一 -->
 		<one-to-one name="card" class="Card"/>
 		
 	</class>
 
</hibernate-mapping>   

身份证配置Card.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping package="com.yiidian.domain">
 
 	<class name="Card" table="t_card_pk">
 		<id name="id" column="id">
 			<generator class="native"></generator>
 		</id>
 		<property name="name" column="name"></property>
 		
 		<!-- 主键关联(一对一) -->
 		<one-to-one name="person" class="Person" constrained="true"/>
 		
 	</class>
 
</hibernate-mapping>   

大家发现,主键关联和之前的唯一关联区别在于Card.hbm.xml的配置使用<one-to-one/>进行映射。

1.4、hibernate.cfg.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
	
<hibernate-configuration>	
	<!-- 连接数据库的参数 -->
<session-factory>
	<!-- 1.连接数据库参数 -->
	<property name="hibernate.connection.driver_class">
		com.mysql.jdbc.Driver
	</property>
	<property name="hibernate.connection.url">
		jdbc:mysql://localhost:3306/hibernate
	</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">root</property>

	<!-- hibernate方言 -->
	<property name="hibernate.dialect">
		org.hibernate.dialect.MySQLDialect
	</property>

	<!-- 2.hibernate扩展参数 -->
	<property name="hibernate.show_sql">true</property>
	<property name="hibernate.format_sql">true</property>
	<property name="hibernate.hbm2ddl.auto">update</property>

	<!-- *.hbm.xml文件 -->
	<mapping resource="com/yiidian/domain/Person.hbm.xml" />
	<mapping resource="com/yiidian/domain/Card.hbm.xml" />
</session-factory>
</hibernate-configuration>	

1.5、执行一对一保存保存

/**
 * 演示Hibernate的一对一关系映射操作
 * 
 * @author http://www.yiidian.com
 * 
 */
public class Demo {

	/**
	 * 添加
	 */
	@Test
	public void test1(){
		Person p = new Person();
		p.setName("小苍");
		
		Card c = new Card();
		c.setName("1001");
		
		p.setCard(c);
		c.setPerson(p);
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		session.save(p);
		session.save(c);
		
		tx.commit();
		session.close();
	}

}

1.6、运行结果

控制台显示:

Hibernate: 
    insert 
    into
        t_person_pk
        (name) 
    values
        (?)
Hibernate: 
    insert 
    into
        t_card_pk
        (name) 
    values
        (?)

一共建立两张表,分别为t_person_pk,t_card_pk。

t_person_pk表数据:

t_card_pk表的数据:

 

源码下载:https://pan.baidu.com/s/1hrC5z6G