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("[email protected]");
		email.add("[email protected]");
		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("[email protected]");
		email.add("[email protected]");
		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());

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

 

 

你可能感兴趣的:(数据结构,Hibernate,xml,.net,Gmail)