当前位置:首页 > 开发 > 编程语言 > Hibernate > 正文

Hibernate配置复合主键 composite primary key (一)

发表于: 2013-11-27   作者:alleni123   来源:转载   浏览次数:
摘要: 这篇是关于如何配置Hibernate实现复合主键的映射功能。 摘自圣思园Hibernate.25的后半部分和26的前半部分。 1.要使用复合主键,对应类Student必须实现Serializable接口。 2.要重写hashCode和equals方法。 重写hashCode和equals方法的原因: Hibernate要判断两个对象是否相同,避免出现两个复合主键相同的对象实例
这篇是关于如何配置Hibernate实现复合主键的映射功能。
摘自圣思园Hibernate.25的后半部分和26的前半部分。


1.要使用复合主键,对应类Student必须实现Serializable接口。
2.要重写hashCode和equals方法。

重写hashCode和equals方法的原因:
Hibernate要判断两个对象是否相同,避免出现两个复合主键相同的对象实例被加入数据库(数据库也不会接收)。
因此Hibernate会通过hashCode和equals方法来判断是否可以将两个对象放入诸如Set这样的集合中去。

Student.java

package composite;

import java.io.Serializable;

public class Student implements Serializable
{	
	//这里用name和cardId作为联合主键
	
	private String cardId;
	
	private String name;
	
	private int age;
	

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + ((cardId == null) ? 0 : cardId.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (cardId == null)
		{
			if (other.cardId != null)
				return false;
		}
		else if (!cardId.equals(other.cardId))
			return false;
		if (name == null)
		{
			if (other.name != null)
				return false;
		}
		else if (!name.equals(other.name))
			return false;
		return true;
	}
}


Student.hbm.xml

<hibernate-mapping package="composite">
	<class name="Student" table="test_student">
	
	<!-- composite-id表示复合主键 -->
	<composite-id>
		<!-- key-property表示组成主键的元素 -->
		<key-property name="cardId" column="card_id" type="string"/>
		<key-property name="name" column="name" type="string"/>
		
	</composite-id>
	 
	 
	 <property name="age" column="age" type="int"/>
	 
	  
	</class>



</hibernate-mapping>
	



运行configure(),会产生以下SQL语句。

create table test_student(
card_id varchar2(255) not null,
name varchar2(255) not null,
age number(10),
primary key(card_id,name));





插入

运行以下插入代码,便会报错了。

	Session session=HibernateUtil.openSession();
		
  		 
		Transaction tx=session.beginTransaction();
		
		Student s1=new Student("111", "alleni", 22);
		
		Student s2=new Student("111","alleni",22);
		
		session.save(s1);
		session.save(s2);
		
		tx.commit();



Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [composite.Student#composite.Student@abc1a76f]
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:179)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:206)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:191)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:764)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:756)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:752)
at composite.Hibernate_1Insert.main(Hibernate_1Insert.java:27)




org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

即是说,这个identifier值已经被session存储了,并且指向已经存在的对象。而再存入另一个对象,也就是s2的时候,又提取出来了同样的identifier。


查询

随便瞎写一个查询语句:
	Student s=(Student) session.get(Student.class,"111");
		
		System.out.println(s.getName());


这里的报错信息是:
org.hibernate.TypeMismatchException: Provided id of the wrong type for class composite.Student. Expected: class composite.Student, got class java.lang.String

提供id类型不正确,期待的是composite.Student类型,而不是java.lang.String.

为什么Student要实现Serializable接口?
在使用get或load方法的时候需要先构建出来该实体类的对象,并且将查询依据(联合主键)设置进去,然后作为get或者load方法的第二个参数传进去即可。
用过Hibernate的就知道,Hibernate的get和load方法接受的都是一个Class和一个Serializable类型对象。



Hibernate API文档:
Object org.hibernate.Session.get(Class clazz, Serializable id)
Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance is already associated with the session, return that instance. This method never returns an uninitialized instance.)


因此在Student实现了Serializable接口之后,我们就可以通过如下的查询方式:

		Session session=HibernateUtil.openSession();
		
		
		//先构建出来查询的依据,一个Student对象。
		Student student_primaryKey=new Student();
		student_primaryKey.setCardId("111");
		student_primaryKey.setName("alleni");
		
		
		Student s=(Student) session.get(Student.class,student_primaryKey);
		
		System.out.println(s.getName());
		System.out.println(s.getAge());




Hibernate配置复合主键 composite primary key (一)

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
在使用hibernate时有时会碰到配置复合主键和使用,例如下面表就是使用了一个复合主键的 那么在配置h
Hibernate中除了使用<generator>来生成主键之外,还可以根据具体的需求让持久化类的标识符属
Hibernate中除了使用<generator>来生成主键之外,还可以根据具体的需求让持久化类的标识符属
Hibernate中除了使用<generator>来生成主键之外,还可以根据具体的需求让持久化类的标识符属
复合主键在表中有多个属性共同确定一个元素,对应到实体类中就有多个属性共同构成主键属性。可以把
Primary key 与Unique Key都是MySQL数据库的唯一性约束。但是二者有很大的区别: 1、Primary key的1
在SOA中,复合服务是非常重要的一个概念。总体来说,按其复合程度,复合服务可以分为:一般意义上的
在SOA中,复合服务是非常重要的一个概念。总体来说,按其复合程度,复合服务可以分为:一般意义上的
上篇文章讨论了继承映射,它是对象模型中最主要的特性,对于继承映射它的主要区分是字段类型的不同
作者:zccst 一、key与primary key区别 CREATE TABLE wh_logrecord ( logrecord_id int(11) NOT NULL
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号