天天看点

注解方式实现 Hibernate 的双向一对多关系的映射

Hibernate注解的方式使用还不太熟悉,现将学习笔记记录如下:

一对多双向关联的注解实现:

现有DashboardWindow 和 DashboardWinParam 两个实体,是父子关系

DashboardWindow(一端):

@Entity
@Table(name="SYS_DASHBOARD_WINDOW")
public class DashboardWindow {//corresponding to APPData
	@Id
	@Column(name="WIN_ID")
	@GenericGenerator(name = "WIN_ID", strategy = "assigned")
	private long id;
	@Column(name="WIN_NAME",length=30)
	private String name;
	@Column(name="WIN_STATUS")//0-Normal  1-Min  2-Max 
	private int status;
	@Column(name="WIN_INDEX")
	private int index;
	@Column(name="DASHBOARD_ID")
	private long parentDsbId;
	@Column(name="WIN_X")
	private int winX;
	@Column(name="WIN_Y")
	private int winY;
	@Column(name="WIN_HEIGHT")
	private int winHeight;
	@Column(name="WIN_WIDTH")
	private int winWidth;
	@Column(name="APP_URL",length=255)
	private String appUrl;
	@Column(name="MODIFY_DATE")
	private Timestamp modifyDate;
	
	@OneToMany(mappedBy="dashboardWindow",cascade={CascadeType.ALL},fetch=FetchType.EAGER)
	private Set<DashboardWinParam> dashboardWinParams; 
	
	public Set<DashboardWinParam> getDashboardWinParams() {
		if(dashboardWinParams == null){
			dashboardWinParams = new HashSet<DashboardWinParam>();
		}
		return dashboardWinParams;
	}
	public void setDashboardWinParams(Set<DashboardWinParam> dashboardWinParams) {
		this.dashboardWinParams = dashboardWinParams;
	}
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getIndex() {
		return index;
	}
	public void setIndex(int index) {
		this.index = index;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(int status) {
		this.status = status;
	}
	public long getParentDsbId() {
		return parentDsbId;
	}
	public void setParentDsbId(long parentDsbId) {
		this.parentDsbId = parentDsbId;
	}
	public int getWinX() {
		return winX;
	}
	public void setWinX(int winX) {
		this.winX = winX;
	}
	public int getWinY() {
		return winY;
	}
	public void setWinY(int winY) {
		this.winY = winY;
	}
	public int getWinHeight() {
		return winHeight;
	}
	public void setWinHeight(int winHeight) {
		this.winHeight = winHeight;
	}
	public int getWinWidth() {
		return winWidth;
	}
	public void setWinWidth(int winWidth) {
		this.winWidth = winWidth;
	}
	public String getAppUrl() {
		return appUrl;
	}
	public void setAppUrl(String appUrl) {
		this.appUrl = appUrl;
	}
	public Timestamp getModifyDate() {
		return modifyDate;
	}
	public void setModifyDate(Timestamp modifyDate) {
		this.modifyDate = modifyDate;
	}
	
}

 
           

DashboardWinParam(多端):

通过@IdClass注释在实体中标注复合主键.

@Entity
@Table(name="SYS_DASHBOARD_WIN_PARAM")
@IdClass(PKWinParam.class)
public class DashboardWinParam {
	private String name;
	private String value;//default value 
	private DashboardWindow dashboardWindow;
	
	@Id
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Column(name="PARAM_VALUE",nullable=false,length=255)
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	@Id
	public DashboardWindow getDashboardWindow() {
		return dashboardWindow;
	}
	public void setDashboardWindow(DashboardWindow dashboardWindow) {
		this.dashboardWindow = dashboardWindow;
	}

}
           

PKWinParam(嵌入的主键类,用于复合主键):

@JoinColumn(name="WIN_ID") 表明DashboardWinParam的外键WIN_ID,指向DashboardWindow的主键列 WIN_ID

@Embeddable
public class PKWinParam implements Serializable {
	
	private DashboardWindow dashboardWindow;
	private String name;

	@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
	@JoinColumn(name="WIN_ID",referencedColumnName="WIN_ID",nullable=false)	
	public DashboardWindow getDashboardWindow() {
		return dashboardWindow;
	}

	public void setDashboardWindow(DashboardWindow dashboardWindow) {
		this.dashboardWindow = dashboardWindow;
	}

	@Column(name="PARAM_NAME",nullable=false,length=50)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null)
			return false;
		if (!(o instanceof PKWinParam))
			return false;
		PKWinParam pk = (PKWinParam) o;
		if (this.dashboardWindow.getId() == pk.getDashboardWindow().getId() && this.name.equals(pk.getName())) {
			return true;
		}
		return true;
	}

	@Override
	public int hashCode() {
		return 31 * this.dashboardWindow.hashCode() + this.name.hashCode();
	}
}
           

作为符合主键类,要满足以下几点要求。

  l 必须实现Serializable接口。

  l  必须有默认的public无参数的构造方法。

  l 必须覆盖equals和hashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity 时,是根据equals的返回值来判断的。本例中,只有对象的name和email值完全相同时或同一个对象时则返回true,否则返回false。 hashCode方法返回当前对象的哈希码,生成的hashCode相同的概率越小越好,算法可以进行优化。