`
SunnyYoona
  • 浏览: 368266 次
社区版块
存档分类
最新评论

[Hibernate开发之路](5)联合主键

 
阅读更多

现在大家都不推荐使用联合主键,关键是因为其需要自己手工维护,比较麻烦。但是一个项目可能因为历史遗留原因,你不得不面对联合主键。

Hibernate联合主键问题解决如下:
可以使用一个组件作为一个实体类的标识符。你的组件类必须满足以下要求:
(1)它必须实现 java.io.Serializable 接口
(2)它必须重新实现 equals() 和 hashCode() 方法,始终和组合关键字在数据库中的概念保持一致
注意:在 Hibernate3 中,第二个要求并非是 Hibernate 强制必须的。但最好这样做。
不能使用一个 IdentifierGenerator 产生组合关键字。一个应用程序必须分配它自己的标识符。

将主键所对应属性提取出一个类(称之为主键类),并且主键类需要实现Serializable接口,重写equals方法与hashCode方法,原因:

在于Hibernate要根据数据库的联合主键来判断某两行记录是否是一样,如果一样那么就认为是同一个对象,如果不一样,那么就认为是不同的对象。

一 XML配置方式

具体做法如下步骤:

(1)将主键所对应属性提取出一个类(称之为主键类),并且主键类需要实现Serializable接口,重写equals方法与hashCode方法

实例如下:

package com.model;

import java.io.Serializable;

//ScoreInfo主键类
//composite-id class must implement Serializable: com.model.ScorePK
public class ScorePK  implements Serializable{
	
	private static final long serialVersionUID = 1L;
	private Integer  studentID;
	private Integer  courseID;
	
	public int getStudentID() {
		return studentID;
	}
	public void setStudentID(int studentID) {
		this.studentID = studentID;
	}
	public int getCourseID() {
		return courseID;
	}
	public void setCourseID(int courseID) {
		this.courseID = courseID;
	}
	
	@Override
	public boolean equals(Object o){
		if(o instanceof ScorePK){
			ScorePK scorePK = (ScorePK)o;
			if(this.studentID == scorePK.studentID && this.courseID == scorePK.courseID){
				return true;
			}
		}
		return false;
	}
	@Override
	public int hashCode(){
		int result = 1;
		result = result + ((this.studentID == null) ? 0 : this.studentID.hashCode());
        result = result + ((this.courseID == null) ? 0 : this.courseID.hashCode());
        return result; 
	}
}

这里要特别注意,如hibernate API文档所述,主键类必须实现java.io.Serializable接口,而且重写equals和hashCode方法,保证主键的唯一性.

(2)实体类(这里不用包含主键所对应的属性)

package com.model;

public class ScoreInfo {
	//联合主键
	private ScorePK scorePK;
	private int score;
	
	public ScorePK getScorePK() {
		return scorePK;
	}
	public void setScorePK(ScorePK scorePK) {
		this.scorePK = scorePK;
	}
	
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
}

(3)配置Hibernate配置文件ScoreInfo.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>
	<class name="com.model.ScoreInfo" table="ScoreInfo">
		<composite-id name = "ScorePK" class = "com.model.ScorePK">
			<key-property name="StudentID"></key-property>
			<key-property name="CourseID"></key-property>
		</composite-id>
		<property name="score" column = "Score"/>
    </class>
</hibernate-mapping>
如果表使用联合主键,你可以映射类的多个属性为标识符属性。 <composite-id>元素接受<key-property> 属性映射和<key-many-to-one>属性映射作为子元素。

<composite-id name = "ScorePK" class = "com.model.ScorePK">
			<key-property name="StudentID"></key-property>
			<key-property name="CourseID"></key-property>
		</composite-id>

这个联合主键就是由StudentID和CourseID构成。

(4)不要忘记在hibernate配置文件中引用映射文件。

<!-- XML配置方式 -->
        <mapping resource="com/model/ScoreInfo.hbm.xml"/>
(5)测试

package com.test;

import org.hibernate.Session;

import com.model.ScoreInfo;
import com.model.ScorePK;
import com.util.HibernateUtil;

public class Test {
	
	public static void main(String[] args) {	
		
		Test mgr = new Test();
		mgr.createAndStoreEvent();
		HibernateUtil.getSessionFactory().close();
    }

    private void createAndStoreEvent() {

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
        ScorePK scorePK = new ScorePK();
        scorePK.setStudentID(2);
        scorePK.setCourseID(1);
        
        ScoreInfo score = new ScoreInfo();
        score.setScorePK(scorePK);
        score.setScore(98);
        
        session.save(score);
        session.getTransaction().commit();
    }
}

辅助类:HibernateUtil

package com.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
	
	private static final SessionFactory sessionFactory;
    static 
    {
        try 
        {
            // Create the SessionFactory from hibernate.cfg.xml
            sessionFactory = new Configuration().configure().buildSessionFactory();
        }
        catch (Throwable ex) 
        {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

二 Annotation注解方式

下面是定义联合主键的几种方式:

(1)将组件类(主键类)注解为@Embeddable,并在实体类中将组件的属性注解为@Id

(2)在实体类中将组件的属性注解为@EmbeddedId

(3)将实体类注解为@IdClass(value = ScorePk.class),并将该实体中所有属于主键的属性都注解为@Id


对于EJB2的开发人员来说@IdClass是很常见的,但是对于Hibernate用户来说就是一个崭新的用法。

组合主键类对应一个实体类的多个字段或属性,而且主键类中定义主键的字段或属性和实体类中对应的字段或属性早类型上必须一致。

实例如下:

(1)将组件类(主键类)注解为@Embeddable

package com.model;

import java.io.Serializable;

import javax.persistence.Embeddable;

//ScoreInfo主键类
//composite-id class must implement Serializable: com.model.ScorePK
@Embeddable
public class ScorePK  implements Serializable{
	
	private static final long serialVersionUID = 1L;
	private Integer  studentID;
	private Integer  courseID;
	
	public int getStudentID() {
		return studentID;
	}
	public void setStudentID(int studentID) {
		this.studentID = studentID;
	}
	public int getCourseID() {
		return courseID;
	}
	public void setCourseID(int courseID) {
		this.courseID = courseID;
	}
	
	@Override
	public boolean equals(Object o){
		if(o instanceof ScorePK){
			ScorePK scorePK = (ScorePK)o;
			if(this.studentID == scorePK.studentID && this.courseID == scorePK.courseID){
				return true;
			}
		}
		return false;
	}
	@Override
	public int hashCode(){
		int result = 1;
		result = result + ((this.studentID == null) ? 0 : this.studentID.hashCode());
        result = result + ((this.courseID == null) ? 0 : this.courseID.hashCode());
        return result; 
	}
}

将在实体类中组件的属性注解为@Id

public class ScoreInfo {
	
	private int studentID;
	private ScorePK scorePK;
	
	@Id
	public ScorePK getScorePK() {
		return scorePK;
	}
	public void setScorePK(ScorePK scorePK) {
		this.scorePK = scorePK;
	}
	
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
}

(2)在实体类中将组件的属性注解为@EmbeddedId

public class ScoreInfo {
	
	private int studentID;
	private ScorePK scorePK;
	
	@EmbeddedId
	public ScorePK getScorePK() {
		return scorePK;
	}
	public void setScorePK(ScorePK scorePK) {
		this.scorePK = scorePK;
	}
	
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
}

(3)将实体类注解为@IdClass(value = ScorePk.class),并将该实体中所有属于主键的属性都注解为@Id

@Entity
@IdClass(value = ScorePk.class)
public class ScoreInfo {
	
	private int studentID;
	private int courseID;
	private int score;
	@Id
	public int getStudentID() {
		return studentID;
	}
	public void setStudentID(int studentID) {
		this.studentID = studentID;
	}
	@Id
	public int getCourseID() {
		return courseID;
	}
	public void setCourseID(int courseID) {
		this.courseID = courseID;
	}
	
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
}












分享到:
评论

相关推荐

    Hibernate笔记 马士兵

    第1课 课程内容 6 第2课 Hibernate UML图 6 第3课 风格 7 第4课 资源 7 第5课 环境准备 7 ...三、 联合主键 24 1、xml方式 24 2、annotation方式 27 第14课 Hibernate核心开发接口(重点) 29 ........

    08.拓薪教育-hibernate4.3的hibernate.cfg.xml基本配置.part2

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    08.拓薪教育-hibernate4.3的hibernate.cfg.xml基本配置.part1

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    05.拓薪教育-hibernate4.3环境搭建上.part1

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    Hibernate实战(第2版 中文高清版)

    第一部分 从Hibernate和EJB 3.0开始  第1章 理解对象/关系持久化   1.1 什么是持久化   1.1.1 关系数据库   1.1.2 理解SQL   1.1.3 在Java中使用SQL   1.1.4 面向对象应用程序中的持久化   1.2 范式不...

    03.拓薪教育-hibernate4.3架构详解

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    01.拓薪教育-hibernate4.3介绍-序

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    07.拓薪教育-hibernate4.3环境搭建下

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    02.拓薪教育-hibernate4.3-orm剖析.part2

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    04.拓薪教育-hibernate4.3官方核心包介绍.part1

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    04.拓薪教育-hibernate4.3官方核心包介绍.part2

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    06.拓薪教育-hibernate4.3环境搭建中.part1

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    06.拓薪教育-hibernate4.3环境搭建中.part2

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    05.拓薪教育-hibernate4.3环境搭建上.part2

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    02.拓薪教育-hibernate4.3-orm剖析.part1

    高级Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,...

    Spring3.x企业应用开发实战(完整版) part1

    17.4.5 使用Hibernate二级缓存 17.5 对持久层进行测试 17.5.1 配置Unitils测试环境 17.5.2 准备测试数据库及测试数据 17.5.3 编写DAO测试基类 17.5.4 编写BoardDao测试用例 17.6 服务层开发 17.6.1 UserService的...

    Spring.3.x企业应用开发实战(完整版).part2

    17.4.5 使用Hibernate二级缓存 17.5 对持久层进行测试 17.5.1 配置Unitils测试环境 17.5.2 准备测试数据库及测试数据 17.5.3 编写DAO测试基类 17.5.4 编写BoardDao测试用例 17.6 服务层开发 17.6.1 UserService的...

    hibernate4从入门到大神(备java基础,mysql,javaee经典框架)

    Hibernate4开发技术:ORM思想,hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate映射技术,Hibernate多表...

Global site tag (gtag.js) - Google Analytics