Hibernate注解实现复杂主键(多主键,外键当主键,主键自动生成,普通主键)...

本文深入探讨了使用Hibernate在数据库中实现复杂主键的方法,特别是涉及联合主键、嵌入类和@EmbeddedId、@Embeddable、@IdClass注解的应用场景。通过实例展示了如何解决实体类设计中遇到的问题,包括联合主键的自动生成、序列或UUID的使用,以及复合主键的设计与实现。
摘要由CSDN通过智能技术生成

最近我的博客老是搬家,最后还是回到开源中国的博客,真心对不起那些加过我贴子收藏的人,我悔过!希望我的贴子能帮助到和我遇到同样问题的朋友!

正题。如何用Hibernate实现复杂主键,@EmbeddedId、@IdClass用哪个实现?

一个表有多个主键,有外键,这个外键还是主键,其他的主键有一个还是自动产生id的,我遇到这个问题要设计实体类的时候也是醉了~

当然反向生成实体类方便很多。但是生成的实体类复合主键用的都是@EmbeddedId、和@Embeddable注解。这种注解需要手动new一个被@Embeddable注解的嵌入类,set完属性后将这个嵌入对象set给@EmbeddedId注解getter,不能使是其中的属性自动产生值。

我一开始找的办法是怎么在被@EmbeddedId或@Embeddable注解的类添加序列或uuid,后来查JPA文档才想起了注解ID还有个@IdClass。发现改写还挺容易的,下面是简化的例子。

反向生成被@EmbeddedId或@Embeddable注解的类:

表对应的实体类:

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import com.kcomdata.entity.PdBvd;
import com.kcomdata.entity.PdBvdIndId;

@Entity
@Table(name = "PD_BVD_IND")
public class PdBvdInd implements java.io.Serializable {

	private PdBvdIndId id;// 这一个联合主键嵌入的类,存放多个主键。
	private PdBvd pdBvd;// 这个会产生一个外键字段BVD_ID,但是表中它还是个主键。

	/**
	 * 嵌套进来的PdBvdIndId类,其属性是多个主键,其中BVD_ID和外键是同一个,所以就同时是主键,ID字段需要使用uuid生成。
	 */
	@EmbeddedId
	@AttributeOverrides({
			@AttributeOverride(name = "bvdId", column = @Column(name = "BVD_ID", nullable = false, length = 50)),
			@AttributeOverride(name = "type", column = @Column(name = "TYPE", nullable = false, length = 50)),
			@AttributeOverride(name = "id", column = @Column(name = "ID", nullable = false, precision = 19)) })
	public PdBvdIndId getId() {
		return this.id;
	}

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

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "BVD_ID", nullable = false, insertable = false, updatable = false)
	public PdBvd getPdBvd() {
		return this.pdBvd;
	}

	public void setPdBvd(PdBvd pdBvd) {
		this.pdBvd = pdBvd;
	}

}

实体类的ID嵌入类:

import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Embeddable;


@Embeddable
public class PdBvdIndId implements java.io.Serializable {

	private String bvdId;
	private String type;
	private BigDecimal id;

	@Column(name = "BVD_ID", nullable = false, length = 50)
	public String getBvdId() {
		return this.bvdId;
	}

	public void setBvdId(String bvdId) {
		this.bvdId = bvdId;
	}

	@Column(name = "TYPE", nullable = false, length = 50)
	public String getType() {
		return this.type;
	}

	public void setType(String type) {
		this.type = type;
	}

	@Column(name = "ID", nullable = false, precision = 19)
	public BigDecimal getId() {
		return id;
	}

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

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

		return ((this.getBvdId() == castOther.getBvdId()) || (this.getBvdId() != null
				&& castOther.getBvdId() != null && this.getBvdId().equals(castOther.getBvdId())))
				&& ((this.getType() == castOther.getType()) || (this.getType() != null
						&& castOther.getType() != null && this.getType()
						.equals(castOther.getType())))
				&& ((this.getId() == castOther.getId()) || (this.getId() != null
						&& castOther.getId() != null && this.getId().equals(castOther.getId())));
	}

	public int hashCode() {
		int result = 17;

		result = 37 * result + (getBvdId() == null ? 0 : this.getBvdId().hashCode());
		result = 37 * result + (getType() == null ? 0 : this.getType().hashCode());
		result = 37 * result + (getId() == null ? 0 : this.getId().hashCode());
		return result;
	}

}

生成的这两个类不能满足其中一个主键用uuid、序列或自动增长生成。改写成@IdClass的步骤:

表对应的实体类:

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;

import com.kcomdata.entity.PdBvd;
import com.kcomdata.entity.PdBvdIndId;

@Entity
@Table(name = "PD_BVD_IND")
@IdClass(PdBvdIndId.class)//指定id类
public class PdBvdInd implements java.io.Serializable {
	
	/* 去掉那个主键类属性,将主键类属性全部搬过来 */
	private String bvdId;//这个属性映射着pdBvd属性生成的外键字段,持久化时需要手动填值,不需要set入关联对象即调用getPdBvd()。
	private String type;//这个主键持久化的时候需要手动填写。
	private String id;//这个用uuid生成,但原表的类型是number(19),uuid需要用varchar存储,将原来的类型改成String。
	
	
	private PdBvd pdBvd;// 这个会产生一个外键字段BVD_ID,但是表中它还是个主键。

	/*这个不需要了删除掉
	
	@EmbeddedId
	@AttributeOverrides({
			@AttributeOverride(name = "bvdId", column = @Column(name = "BVD_ID", nullable = false, length = 50)),
			@AttributeOverride(name = "type", column = @Column(name = "TYPE", nullable = false, length = 50)),
			@AttributeOverride(name = "id", column = @Column(name = "ID", nullable = false, precision = 19)) })
	public PdBvdIndId getId() {
		return this.id;
	}

	public void setId(PdBvdIndId id) {
		this.id = id;
		
	}*/

	@ManyToOne(fetch = FetchType.LAZY)//这是外键,非空的。
	@JoinColumn(name = "BVD_ID", nullable = false, insertable = false, updatable = false)
	public PdBvd getPdBvd() {
		return this.pdBvd;
	}

	public void setPdBvd(PdBvd pdBvd) {
		this.pdBvd = pdBvd;
	}

	@Id//这个不需要生成策略,它映射着外键,插入时需要手动插入数据,外键也就有了数据,所以持久化时不需要调用getPdBvd()
	@Column(name = "BVD_ID", nullable = false, length = 50)
	public String getBvdId() {
		return bvdId;
	}

	public void setBvdId(String bvdId) {
		this.bvdId = bvdId;
	}
	
	@Id//这个不需要生成策略,但持久化时要手动set值
	@Column(name = "TYPE", nullable = false, length = 50)
	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
	
	@Id//这个是用uuid自动生成
	@GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
	@Column(name = "ID", nullable = false)
	public String getId() {
		return id;
	}

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

}

@IdClass的复合组件类:

public class PdBvdIndId implements java.io.Serializable {

	private String bvdId;
	private String type;
	private String id;//将原来的BigDecimal改成String,用来保存uuid。

	public String getBvdId() {
		return this.bvdId;
	}

	public void setBvdId(String bvdId) {
		this.bvdId = bvdId;
	}

	public String getType() {
		return this.type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getId() {
		return id;
	}

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

	/**
	 * 作为@IdClass的复合主键类,必须重写equals方法和hashCode(),但是从数据库反向生成的@Embeddable类也必须重写,
	 * 所以这里已经自动生成。
	 */
	public boolean equals(Object other) {
		if ((this == other))
			return true;
		if ((other == null))
			return false;
		if (!(other instanceof PdBvdIndId))
			return false;
		PdBvdIndId castOther = (PdBvdIndId) other;

		return ((this.getBvdId() == castOther.getBvdId()) || (this.getBvdId() != null
				&& castOther.getBvdId() != null && this.getBvdId().equals(castOther.getBvdId())))
				&& ((this.getType() == castOther.getType()) || (this.getType() != null
						&& castOther.getType() != null && this.getType()
						.equals(castOther.getType())))
				&& ((this.getId() == castOther.getId()) || (this.getId() != null
						&& castOther.getId() != null && this.getId().equals(castOther.getId())));
	}

	public int hashCode() {
		int result = 17;

		result = 37 * result + (getBvdId() == null ? 0 : this.getBvdId().hashCode());
		result = 37 * result + (getType() == null ? 0 : this.getType().hashCode());
		result = 37 * result + (getId() == null ? 0 : this.getId().hashCode());
		return result;
	}

}

表结构:

PD_BVD_IND表名
BVD_ID   varchar2(50)
TYPEvarchar2(50)
IDvarchar2(255)

主键:BVD_ID、TYPE、ID(BVD_ID来自外键,TYPE手动填写,ID自动生成)

外键:BVD_ID



转载于:https://my.oschina.net/js99st/blog/418030

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值