`

hibernate之复合主键

阅读更多

对于系统设计而言,应该尽量减少和避免在数据库表中引入与业务逻辑相关的主键关系;将业务逻辑主键引入库表,使得底层数据库表结构与业务逻辑想耦合,如果业务逻辑的变化,将很可能对底层数据库结构产生连带应影响;

例如:在项目开发初期,业务逻辑认为系统中的用户名是不可以重复的,随着新的需求产生,出现了用户名可重复的可能性,这样的话,我们就得从底层数据库开始更改,但是在某些关键的系统中,这样更在某些关键地方,将是一个大工程,这样的工作将难以接受;

这样,复合主键的引入,很大程度上意味着业务逻辑已经侵入到数据存储逻辑之中。因此在新的系统中,应该避免这样的设计;然而在旧的系统中遇到这样的情况,如果有复合主键的支持就显得很必要;

复合主键的使用,以Tuser为蓝本,将那么拆分成两个部分,firstname,lastname,以他们作为复合主键;对于复合主键而言,我们可以通过两种方式确定主键(Hibernate中通过<composite-id>定义复合主键):

 

  • 基于实体类的复合主键

复合主键是由实体类的属性组成,此时,实体类本身也扮演着复合主键类的角色;定义如下(Hibernate要求复合主键类要实现equals和hasCode方法,以作为不同数据之间的标识):

Tuser类:

 

public class Tuser implements Serializable {

	private String firstName;
	private String lastName;

	private List email = new ArrayList();
	private List address = new ArrayList();

        get/set()....

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((address == null) ? 0 : address.hashCode());
		result = prime * result + ((email == null) ? 0 : email.hashCode());
		result = prime * result
				+ ((firstName == null) ? 0 : firstName.hashCode());
		result = prime * result
				+ ((lastName == null) ? 0 : lastName.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;
		Tuser other = (Tuser) obj;
		if (address == null) {
			if (other.address != null)
				return false;
		} else if (!address.equals(other.address))
			return false;
		if (email == null) {
			if (other.email != null)
				return false;
		} else if (!email.equals(other.email))
			return false;
		if (firstName == null) {
			if (other.firstName != null)
				return false;
		} else if (!firstName.equals(other.firstName))
			return false;
		if (lastName == null) {
			if (other.lastName != null)
				return false;
		} else if (!lastName.equals(other.lastName))
			return false;
		return true;
	}
}
 

 

Tuser.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.keith">

	<class name="Tuser" table="tUser">
		<composite-id>
			<key-property name="firstName" />
			<key-property name="lastName" />
		</composite-id>
		<property name="email" type="com.keith.EmailList"></property>
	</class>
</hibernate-mapping>

 

 先添加一条数据(测试代码):

 

                Tuser tUser = new Tuser();
		tUser.setFirstName("keke");
		tUser.setLastName("EEE");
		
		List email = new ArrayList();
		email.add("keith@gmail.com");
		email.add("keith@sina.coom");
		tUser.setEmail(email);
		session.save(tUser);

 

 看下输出的SQL:

 

Hibernate:  insert into   tUser(email, firstName, lastName) values (?, ?, ?)

 

 虽然数据已经添加进去了,但是对于表结构还有点模糊,看下表结构:

 

CREATE TABLE `tuser` (
  `firstName` varchar(255) NOT NULL,
  `lastName` varchar(255) NOT NULL,
  `email` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`firstName`,`lastName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 这样就一目了然了,测试下如何查询(以tUser作为识别对象,通过session.load()方法加载数据):

 

		Tuser tUser = new Tuser();
		tUser.setFirstName("keke");
		tUser.setLastName("EEE");
		tUser = (Tuser) session.load(Tuser.class, tUser);
		System.out.println("tUser's Email:"+tUser.getEmail());
  •  基于主键类的复合主键

 

我们也可以将主键逻辑加以隔离,以一个单独的主键类对复合主键进行描述;这样我们就需要一个TuserPK类(用来装Tuser的主键):

 

package com.keith;

public class TuserPK implements java.io.Serializable {
	private String firstName;
	private String lastName;

        get()/set()....



	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((firstName == null) ? 0 : firstName.hashCode());
		result = prime * result
				+ ((lastName == null) ? 0 : lastName.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;
		TuserPK other = (TuserPK) obj;
		if (firstName == null) {
			if (other.firstName != null)
				return false;
		} else if (!firstName.equals(other.firstName))
			return false;
		if (lastName == null) {
			if (other.lastName != null)
				return false;
		} else if (!lastName.equals(other.lastName))
			return false;
		return true;
	}
}

 

 在Tuser中就这样:

 

public class Tuser implements Serializable {

	private TuserPK tuserpk;

	private List email = new ArrayList();
	private List address = new ArrayList();

        get()/set()...


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((address == null) ? 0 : address.hashCode());
		result = prime * result + ((email == null) ? 0 : email.hashCode());
		result = prime * result + ((tuserpk == null) ? 0 : tuserpk.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;
		Tuser other = (Tuser) obj;
		if (address == null) {
			if (other.address != null)
				return false;
		} else if (!address.equals(other.address))
			return false;
		if (email == null) {
			if (other.email != null)
				return false;
		} else if (!email.equals(other.email))
			return false;
		if (tuserpk == null) {
			if (other.tuserpk != null)
				return false;
		} else if (!tuserpk.equals(other.tuserpk))
			return false;
		return true;
	}
}

 

 属性文件里要这样(<composite-id name="tuserpk" class="TuserPK">):

 

<?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.keith">

	<class name="Tuser" table="tUser">
		<composite-id name="tuserpk" class="TuserPK">
			<key-property name="firstName" />
			<key-property name="lastName" />
		</composite-id>
		<property name="email" type="com.keith.EmailList"></property>
	</class>
</hibernate-mapping>

添加一条数据:

 

		Tuser tUser = new Tuser();
		TuserPK tUserPk = new TuserPK();
		tUserPk.setFirstName("aaa");
		tUserPk.setLastName("bbb");
		
		tUser.setTuserpk(tUserPk);
		List email = new ArrayList();
		email.add("keith@gmail.com");
		email.add("keith@sina.coom");
		tUser.setEmail(email);
		session.save(tUser);
 

根据主键进行查询:

 

		
		Tuser tUser = new Tuser();
		TuserPK tUserPk = new TuserPK();
		tUserPk.setFirstName("aaa");
		tUserPk.setLastName("bbb");
		tUser = (Tuser) session.load(Tuser.class, tUserPk);
		System.out.println("tUser's Email:"+tUser.getEmail());

 以上就是复合主键的用法!

 

 

2
3
分享到:
评论

相关推荐

    hibernate复合主键配置和使用

    《Hibernate复合主键配置与使用详解》 在Java开发中,Hibernate作为一款强大的ORM框架,大大简化了数据库操作。然而,当我们面临复杂的数据表结构,尤其是涉及到复合主键时,如何在Hibernate中进行配置和使用就显得...

    Hibernate复合主键

    "Hibernate复合主键" Hibernate复合主键是指在 Hibernate 框架中使用复合主键来唯一标识一个实体。复合主键是指由多个字段组成的主键,用于唯一标识一个实体。在本例中,我们将通过一个简单的复合主键的做关联类的...

    hibernate复合主键映射

    在Java的持久化框架Hibernate中,复合主键(Composite Key)是一种特殊的数据模型,它用于表示由多个属性共同构成的唯一标识。这种设计通常出现在实体类的某些属性组合起来才能唯一确定一个对象的情况下。本篇文章将...

    hibernate复合主键设置

    在Java的持久化框架Hibernate中,复合主键(Composite Key)是一种特殊的数据结构,用于处理具有多个字段作为唯一标识的情况。本教程将深入探讨如何在Hibernate中设置复合主键,并提供一个可直接使用的配置示例。 ...

    hibernate 无主键表映射

    通过以上的解释,我们可以看到,虽然无主键表在数据库中并不常见,但在某些特定场景下,如复合主键,Hibernate提供了一套完整的解决方案。所提供的资源包括一个简单的Demo,可以实际运行并理解无主键表映射的实现...

    hibernate复合主键的实例

    当一个表的主键由两个或更多个字段组成时,我们称之为复合主键。复合主键确保了这些字段组合的唯一性,而单个字段可能不是唯一的。 二、为什么要使用复合主键? 在某些情况下,单一字段无法唯一标识表中的记录,...

    Hibernate复合主键.

    本篇文章将深入探讨Hibernate如何支持和管理复合主键。 一、理解复合主键 在数据库设计中,复合主键是一种特殊情况,当单个字段不能唯一标识表中的每一行时,可以使用两个或多个字段的组合来创建唯一的标识。例如...

    Hibernate复合主键视频2

    请更名为 Hibernate复合主键.part2.rar

    Hibernate复合主键3

    更名为 Hibernate复合主键.part3.rar

    演示怎样在Hibernate中使用复合主键

    如果使用Hibernate开发legacy的数据库应用,对于数据库表中有使用字符串作为主键或者使用复合主键情况,那么对于这些情况的影射档是比较麻烦的。该示例应用演示了两张表ITEM和CATEGORY_ITEM表有主外键关系,并且ITEM...

    Hibernate复合主键part1

    本章讲解Hibernate中对数据库复合主键的支持

    hibernate3 注释生成复合主键或者嵌入式主键的方法及实例.doc

    这篇文档将介绍如何使用Hibernate注解来生成复合主键或嵌入式主键。 复合主键(Composite Key)是指由两个或更多个列共同构成的唯一标识,而嵌入式主键(Embedded Key)则是将主键字段嵌入到实体类内部。在不使用...

    Java的Hibernate框架中复合主键映射的创建和使用教程

    在Java的Hibernate框架中,复合主键映射是一种处理多列组合成主键的情况,它使得在数据库表中由两个或更多个字段组成的主键能够被正确地映射到实体类。在使用复合主键时,我们需要遵循一定的步骤和规则。 首先,...

    复合主键@IdClass

    本文将详细探讨如何在SSH框架(Spring、Struts、Hibernate)中的实体类使用`@IdClass`注解来定义复合主键,并阐述其使用方法及注意事项。 #### 二、复合主键的定义与应用场景 复合主键是指由两个或两个以上的字段...

    hibernate复合主键及关联的实现

    博文链接:https://balaschen.iteye.com/blog/155127

Global site tag (gtag.js) - Google Analytics