`

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

阅读更多
这篇是关于如何配置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 体系结构与配置 参考文档(html)

    触发器实现的主键生成器(Primary keys assigned by triggers) 5.1.5. composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. timestamp (可选) 5.1.9. property 5.1.10. 多对...

    Hibernate 中文 html 帮助文档

    触发器实现的主键生成器(Primary keys assigned by triggers) 5.1.5. composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. timestamp (可选) 5.1.9. property 5.1.10. 多对一...

    最全Hibernate 参考文档

    触发器实现的主键生成器(Primary keys assigned by triggers) 5.1.5. composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. timestamp (optional) 5.1.9. property 5.1.10. 多对一...

    Hibernate教程

    触发器实现的主键生成器(Primary keys assigned by triggers) 6.1.5. composite-id 6.1.6. 鉴别器(discriminator) 6.1.7. 版本(version)(可选) 6.1.8. timestamp (optional) 6.1.9. property 6.1.10. 多...

    Hibernate3的帮助文档

    触发器实现的主键生成器(Primary keys assigned by triggers) 6.1.5. composite-id 6.1.6. 鉴别器(discriminator) 6.1.7. 版本(version)(可选) 6.1.8. timestamp (optional) 6.1.9. property 6.1.10. 多...

    hibernate3.04中文文档.chm

    触发器实现的主键生成器(Primary keys assigned by triggers) 6.1.5. composite-id 6.1.6. 鉴别器(discriminator) 6.1.7. 版本(version)(可选) 6.1.8. timestamp (optional) 6.1.9. property 6.1.10. ...

    hibernate 框架详解

    触发器实现的主键生成器(Primary keys assigned by triggers) 6.1.5. composite-id 6.1.6. 鉴别器(discriminator) 6.1.7. 版本(version)(可选) 6.1.8. timestamp (optional) 6.1.9. property 6.1.10. ...

    Hibernate3+中文参考文档

    触发器实现的主键生成器(Primary keys assigned by triggers) 5.1.5. composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. timestamp (optional) 5.1.9. property 5.1.10. 多对一...

    Hibernate参考文档

    触发器实现的主键生成器(Primary keys assigned by triggers) 5.1.5. composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. timestamp (可选) 5.1.9. property 5.1.10. 多对一...

    Hibernate Reference Documentation3.1

    Table of Contents Preface 1. Introduction to Hibernate ... Many-to-many with shared composite key attribute 23.4.4. Content based discrimination 23.4.5. Associations on alternate keys 24. Best Practices

    jpa-hibernate-tutorials:带有Spring Boot和Spring-Data-JPA的Hibernate教程

    Spring Boot和JPA的Hibernate教程和演示

Global site tag (gtag.js) - Google Analytics