欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

10 15 Hibernate之复合主键映射

程序员文章站 2022-09-14 13:36:04
文章目录1 基于HBM文件的配置2 Annotation配置首先在开发之中复合主键是一中强烈不建议使用的技术,在任何一张数据表里面如果要设置主键应该只设置一个字段,但是复合主键毕竟属于标准的SQL语法,所以在Hibernate或者是JPA之中也都有复合主键的定义支持。范例:数据库脚本-- 删除数据表DROP TABLE IF EXISTS member;-- 创建数据表CREATE TABLE member(mid VARCHAR(50),mname VARCHAR(50),mage...

首先在开发之中复合主键是一中强烈不建议使用的技术,在任何一张数据表里面如果要设置主键应该只设置一个字段,但是复合主键毕竟属于标准的SQL语法,所以在Hibernate或者是JPA之中也都有复合主键的定义支持。
范例:数据库脚本

-- 删除数据表
DROP TABLE IF EXISTS member;
-- 创建数据表
CREATE TABLE member(
	mid VARCHAR(50),
	mname VARCHAR(50),
	mage INT,
	CONSTRAINT pk_mid_name PRIMARY KEY(mid,name)
);

此时设置了两个主键,但是一定要记住一点,主键不应该重复,所以在随后生成Hibernate操作的时候就要观察它生成类的形式。

1 基于HBM文件的配置

10 15 Hibernate之复合主键映射
范例:定义MemberId类

@SuppressWarnings("serial")
public class MemberId implements java.io.Serializable {

	// Fields

	private String mid;
	private String mname;
}

为了能够确定唯一,在这个MemberId类里面必须要覆写equals()和hashCode()两个方法。
范例:在Member类里面利用MemberId来描述复合主键

@SuppressWarnings("serial")
public class Member implements java.io.Serializable {

	// Fields

	private MemberId id;
	private Integer mage;
}

随后需要观察Member.hbm.xml文件的组成。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="org.lks.pojo.Member" table="member" catalog="hedb">
    	<!-- 取代的是id元素,表示此时的id是一个复合主键 -->
        <composite-id name="id" class="org.lks.pojo.MemberId">
            <key-property name="mid" type="java.lang.String">
                <column name="mid" length="50" />
            </key-property>
            <key-property name="mname" type="java.lang.String">
                <column name="mname" length="50" />
            </key-property>
        </composite-id>
        <property name="mage" type="java.lang.Integer">
            <column name="mage" />
        </property>
    </class>
</hibernate-mapping>

范例:测试代码

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;
import org.lks.pojo.MemberId;

public class TestMemberInsert {

	public static void main(String[] args) {
		MemberId id = new MemberId();
		id.setMid("3161301220");
		id.setMname("lks");
		Member vo = new Member();
		vo.setId(id);
		vo.setMage(23);
		HibernateSessionFactory.getSession().save(vo);
		HibernateSessionFactory.getSession().beginTransaction().commit();
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

Hibernate: 
    insert 
    into
        hedb.member
        (mage, mid, mname) 
    values
        (?, ?, ?)

此时信息可以正常保存(复合主键不重复)。

当然在进行数据查询的时候也有一些需要注意的概念,既然ID不能够重复,所以在数据查询中使用的get()方法来讲就必须考虑到复合主键不能重复的特点,所以才覆写了hashCode()以及equals()方法。
范例:数据查询

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;
import org.lks.pojo.MemberId;

public class TestMemberGet {

	public static void main(String[] args) {
		MemberId id = new MemberId();
		id.setMid("3161301220");
		id.setMname("lks");
		Member vo = (Member)HibernateSessionFactory.getSession().get(Member.class, id);
		System.out.println(vo);
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

Hibernate: 
    select
        member0_.mid as mid1_0_0_,
        member0_.mname as mname2_0_0_,
        member0_.mage as mage3_0_0_ 
    from
        hedb.member member0_ 
    where
        member0_.mid=? 
        and member0_.mname=?
org.lks.pojo.Member@3d7fa3ae

所有的类的属性都会自动的根据配置进行不同类型的关系组成。

2 Annotation配置

虽然复合主键出现较少,但是在JPA的开发标准中依然支持了复合主键映射,并且这个复合主键的映射与之前的细粒度划分不同,它可以完美的配置。
范例:观察生成的MemberId程序类

package org.lks.pojo;

import javax.persistence.Column;
import javax.persistence.Embeddable;

/**
 * MemberId entity. @author MyEclipse Persistence Tools
 */
@SuppressWarnings("serial")
@Embeddable

public class MemberId implements java.io.Serializable {

	// Fields

	private String mid;
	private String mname;

	// Constructors

	/** default constructor */
	public MemberId() {
	}

	/** full constructor */
	public MemberId(String mid, String mname) {
		this.mid = mid;
		this.mname = mname;
	}

	// Property accessors

	@Column(name = "mid", nullable = false, length = 50)

	public String getMid() {
		return this.mid;
	}

	public void setMid(String mid) {
		this.mid = mid;
	}

	@Column(name = "mname", nullable = false, length = 50)

	public String getMname() {
		return this.mname;
	}

	public void setMname(String mname) {
		this.mname = mname;
	}

	public boolean equals(Object other) {
		if ((this == other))
			return true;
		if ((other == null))
			return false;
		if (!(other instanceof MemberId))
			return false;
		MemberId castOther = (MemberId) other;

		return ((this.getMid() == castOther.getMid())
				|| (this.getMid() != null && castOther.getMid() != null && this.getMid().equals(castOther.getMid())))
				&& ((this.getMname() == castOther.getMname()) || (this.getMname() != null
						&& castOther.getMname() != null && this.getMname().equals(castOther.getMname())));
	}

	public int hashCode() {
		int result = 17;

		result = 37 * result + (getMid() == null ? 0 : this.getMid().hashCode());
		result = 37 * result + (getMname() == null ? 0 : this.getMname().hashCode());
		return result;
	}

}

范例:观察Member.java类

package org.lks.pojo;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;

/**
 * Member entity. @author MyEclipse Persistence Tools
 */
@SuppressWarnings("serial")
@Entity
@Table(name = "member", catalog = "hedb")

public class Member implements java.io.Serializable {

	// Fields

	private MemberId id;
	private Integer mage;

	// Constructors

	/** default constructor */
	public Member() {
	}

	/** minimal constructor */
	public Member(MemberId id) {
		this.id = id;
	}

	/** full constructor */
	public Member(MemberId id, Integer mage) {
		this.id = id;
		this.mage = mage;
	}

	// Property accessors
	@EmbeddedId

	@AttributeOverrides({
			@AttributeOverride(name = "mid", column = @Column(name = "mid", nullable = false, length = 50)),
			@AttributeOverride(name = "mname", column = @Column(name = "mname", nullable = false, length = 50)) })

	public MemberId getId() {
		return this.id;
	}

	public void setId(MemberId id) {
		this.id = id;
	}

	@Column(name = "mage")

	public Integer getMage() {
		return this.mage;
	}

	public void setMage(Integer mage) {
		this.mage = mage;
	}

}

由于有开发工具的支持,使用复合主键比较方便。

本文地址:https://blog.csdn.net/weixin_43762330/article/details/107139357