10 15 Hibernate之复合主键映射
首先在开发之中复合主键是一中强烈不建议使用的技术,在任何一张数据表里面如果要设置主键应该只设置一个字段,但是复合主键毕竟属于标准的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
上一篇: Python网络爬虫与信息提取学习
下一篇: Chapter 1 - 数据库和SQL