`

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 无主键表映射

    这种情况通常出现在那些通过多个字段共同唯一标识一条记录的复合主键(Composite Key)场景。本文将详细介绍如何在Hibernate中进行无主键表映射,并结合提供的资源进行说明。 首先,我们要理解什么是复合主键。在...

    hibernate联合主键全攻略

    联合主键(Composite Primary Key),是指在数据库表中使用两个或多个字段共同作为主键来唯一标识每一行记录。这种方式在实际应用中非常常见,尤其是在需要通过多维度数据来确定唯一性的场景下。 ### Hibernate联合...

    hibernate基础 入门/ hibernate basic

    6. **Composite Primary Key**:复合主键,用于标识表中的记录,当单一字段不足以唯一标识一条记录时使用。 **SessionFactory的作用**: - **创建Session实例**:SessionFactory负责创建Session实例,并管理这些...

    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. 多对...

    jPA+hibernate

    **联合主键(Composite Primary Key)**在JPA中,当一个实体的主键由两个或更多个字段组成时,我们称之为联合主键。`JPACompositePK`示例将说明如何使用`@Embeddable`和`@EmbeddedId`注解来定义这样的主键。 在这些...

    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. 多...

    实用JPA开发指南----jpa核心技术(关联关系等的配置高级配置)

    4. **复合主键(Composite Primary Keys)**: 当一个实体的主键由两个或更多字段组成时,可以使用`@IdClass`或`@EmbeddedId`注解来定义复合主键。 5. **双向关联(Bidirectional Relationships)**: 在两个实体之间...

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

    **六、复合主键(Composite Primary Key)** 当一个实体的主键由两个或更多个属性组成时,可以使用@EmbeddedId和@Embeddable注解定义复合主键。 **七、Element Collection** Element Collection用于将非实体类型的...

    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. 多...

    EJB 注释精解(pdf版)

    复合主键(Composite Primary Key) 复合主键是指使用多个属性变量(表中的多列)联合起来作为主键。为了实现复合主键,需要编写一个复合主键类(CompositePrimaryKeyClass),并遵循以下规则: - **复合主键类...

    eib3.0中的注解

    复合主键 (Composite Primary Key) - **定义**:当需要使用多个属性变量(表中的多列)联合起来作为主键时,就需要使用复合主键。复合主键要求开发者自定义一个复合主键类。 - **示例**: ```java @Embeddable ...

    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. 多对一...

    EJB3_JPA文档

    2. 联合主键(Composite Primary Key) 对于需要多个字段共同作为主键的情况,JPA提供了@Embeddable和@EmbeddedId注解来定义复合主键类。 3. 链接查询(Association Queries) JPA允许在查询中直接引用实体的关联...

    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. 多对一...

    jpa 全面学习资料

    - **复合主键(Composite Key)**: 当主键由多个字段组成时的处理。 - ** Criteria 查询**: 动态构建查询的API,提供更多灵活性。 **6. JPA实战** 实战部分通常包含实际项目中的应用案例,如: - **Spring Boot + ...

    EJB中的注释.pdf

    #### 六、复合主键(Composite Primary Key) 实体Bean还可以支持复合主键,即主键由多个属性共同组成。这在某些应用场景中非常有用,例如当实体之间的关联关系较为复杂时。 总结而言,EJB中的注解为开发者提供了一...

Global site tag (gtag.js) - Google Analytics