现在的位置: 首页 > 综合 > 正文

Hibernate一对一主键关联映射(单向)

2018年06月05日 ⁄ 综合 ⁄ 共 2970字 ⁄ 字号 评论关闭

Hibernate一对一主键关联映射(单向关联Person——>IDCard即通过Person可以加载IDCard,反过来则不可以)。

映射的数据库表:

原理:让两个实体的主键一样,这样就不需要加入多余的字段了。

Person.java:

public class Person {

	private Integer id;
	private String name;

	/*定义Person和IDCard的关系(单向一对一)*/
	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;
	}

	
}

注:因为是单向关联,且从Person可以关联到IDCard,所以在Person中要添加IDCard的引用。

IDCard.java:

public class IDCard {

	private Integer id;
	private String cardNo;

	public Integer getId() {
		return id;
	}

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

	public String getCardNo() {
		return cardNo;
	}

	public void setCardNo(String cardNo) {
		this.cardNo = cardNo;
	}

}

注:因为是单向关联,且从IDCard不能关联到Person,所以IDCard只是一个普通的javaBean,不需要添加任何对象的引用。

Person.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lixue.bean">
	<class name="Person" table="t_person">
		<id name="id">
		<!-- 采用foreign生成策略,foreign回去的关联对象的标识 -->
			<generator class="foreign">
			<!-- 通过property来表示要关联的对象 -->
			<param name="property">idCard</param>
			</generator>
		</id>
		<property name="name"/>
		<!-- 
			one-to-one指示Hibernate如何加载其关联对象,默认根据主键加载
			也就是拿到关系字段值,根据对端的主键来加载关联对象
			
			constrained="true"标识当前主键(person的主键)还是一个外键
			参照对端的主键(IdCard的主键),也就是会生成外键约束的语句
		 -->
		 <one-to-one name="idCard" constrained="true"/>
	</class>
</hibernate-mapping>

注:单向一对一主键关联映射,原理是让两个实体的主键保持一致,也就是说,类的主键生成策略要改为foreign,其他解释见注释。

IDCard.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lixue.bean">
	<class name="IDCard" table="t_idCard">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="cardNo"/>
		
	</class>
</hibernate-mapping>

注:IDCard是一个普通的javaBean,所以它的映射文件非常简单。

测试添加:

public void testSave1(){
		/*定义Session和事物*/
		Session session = null;
		Transaction transaction = null;
		
		try {
			/*获取Session并开启事物*/
			session = HibernateUtils.getSession();
			transaction = session.beginTransaction();
			
			/*创建身份证并设置属性*/
			IDCard idCard = new IDCard();
			idCard.setCardNo("367578677545348879");
			
			/*创建人并设置属性和关联*/
			Person person = new Person();
			person.setName("习近平");
			person.setIdCard(idCard);
			
			/*我们可以发现没有抛出TransientObjectException
			 * 这不科学啊,我们并没有保存IDCard对象,它还是Transient状态啊,
			 * 怎么可能不报错呢?其实这是由一对一关联映射的特性决定的,它必须先
			 * 保存关联对象Idcard,这样它采用foreign映射策略才能取得对象的标识
			 * 也就默认了cascade属性所导致的
			 */
			session.save(person);
			/*提交事物*/
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
			transaction.rollback();
		} finally{
			HibernateUtils.closeSession(session);
		}
	}
	

注:单向一对一主键关联映射,默认是cascade级联操作的,这就是为什么我们不需要显示的保存IDCard对象,也可以保存Person。


测试查询:

public void testFind(){
		
		/*获取Person对象*/
		Person person = (Person) HibernateUtils.getSession().get(Person.class, 1);
		/*获取Person的name属性*/
		System.out.println("person.name=" + person.getName());
		/*获取Person关联的IDCard的idcardNo*/
		System.out.println("person.idCard.idCardNo=" + person.getIdCard().getCardNo());
	}

注:因为是单向的一对一关联映射,所以可以从Person获取IDCard的属性。

抱歉!评论已关闭.