乘风原创程序

  • 10 15 Hibernate之复合主键映射
  • 2020/7/7 13:37:11
  • 首先在开发之中复合主键是一中强烈不建议使用的技术,在任何一张数据表里面如果要设置主键应该只设置一个字段,但是复合主键毕竟属于标准的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文件的配置


    范例:定义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