Hibernate 无主键表(复合主键)映射

1. 为什么要有复合主键映射

在现实中我们可能会遇到许多表可能是没有主键的,那么我们对其做映射后使用会是什么样的结果?能正常得到我们想要的吗?结果应该是得不到想要的结果,而得到的可能会是如下的报错:

Caused by:org.hibernate.AnnotationException: No identifier specified for entity: xxx.xxx.xxx

这个结果告诉我们:Hibernate映射表是需要主键的。

所以复合主键映射就应运而生了。

2. 注意点

复合主键使用一个可嵌入的类作为主键表示,因此你需要使用@Id@Embeddable两个注解.还有一种方式是使用@EmbeddedId注解.当然还有一种方法那就是——使用@IdClass注解。具体请查看【hibernate-annotations-3.4.0.GA 2.2.6.映射复合主键与外键】。

当然,只需要选择其中的一种就可以了。^_^

注意所依赖的类必须实现 serializable以及实现equals()/hashCode()方法.

举一个具体事例:

2.1. User.java

  1. <span style="font-size: 12px;">package com.sourcefour.bean;
  2. // default package
  3. import javax.persistence.AttributeOverride;
  4. import javax.persistence.AttributeOverrides;
  5. import javax.persistence.Column;
  6. import javax.persistence.EmbeddedId;
  7. import javax.persistence.Entity;
  8. import javax.persistence.Table;
  9. /**
  10. * User entity. @author MyEclipse Persistence Tools
  11. */
  12. @Entity
  13. @Table (name="t_user_composite_pk"
  14. )
  15. public class User implements java.io.Serializable {
  16. // Fields
  17. private UserId id;
  18. // Constructors
  19. /** default constructor */
  20. public User() {
  21. }
  22. /** full constructor */
  23. public User(UserId id) {
  24. this.id = id;
  25. }
  26. // Property accessors
  27. @EmbeddedId
  28. @AttributeOverrides( {
  29. @AttributeOverride(name="intId", column=@Column (name="intId", nullable=false) ),
  30. @AttributeOverride(name="varcName", column=@Column (name="varcName", length=50) ),
  31. @AttributeOverride(name="varcAddress", column=@Column (name="varcAddress", length=50) ),
  32. @AttributeOverride(name="intAge", column=@Column (name="intAge", nullable=false) ) } )
  33. public UserId getId() {
  34. return this.id;
  35. }
  36. public void setId(UserId id) {
  37. this.id = id;
  38. }
  39. }
  40. </span>
package com.sourcefour.bean;
// default package

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


/**
 * User entity. @author  MyEclipse Persistence Tools
 */
@Entity
@Table(name="t_user_composite_pk"
)

public class User  implements java.io.Serializable {


    // Fields    

     private UserId id;


    // Constructors

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

    
    /** full constructor */
    public User(UserId id) {
        this.id = id;
    }

   
    // Property accessors
    @EmbeddedId
    
    @AttributeOverrides( {
        @AttributeOverride(name="intId", column=@Column(name="intId", nullable=false) ), 
        @AttributeOverride(name="varcName", column=@Column(name="varcName", length=50) ), 
        @AttributeOverride(name="varcAddress", column=@Column(name="varcAddress", length=50) ), 
        @AttributeOverride(name="intAge", column=@Column(name="intAge", nullable=false) ) } )

    public UserId getId() {
        return this.id;
    }
    
    public void setId(UserId id) {
        this.id = id;
    }
}

2.2. UserId.java

  1. <span style="font-size: 12px;">package com.sourcefour.bean;
  2. // default package
  3. import javax.persistence.Column;
  4. import javax.persistence.Embeddable;
  5. /**
  6. * UserId entity. @author MyEclipse Persistence Tools
  7. */
  8. @Embeddable
  9. public class UserId implements java.io.Serializable {
  10. // Fields
  11. private int intId;
  12. private String varcName;
  13. private String varcAddress;
  14. private int intAge;
  15. // Constructors
  16. /** default constructor */
  17. public UserId() {
  18. }
  19. /** minimal constructor */
  20. public UserId(int intId, int intAge) {
  21. this.intId = intId;
  22. this.intAge = intAge;
  23. }
  24. /** full constructor */
  25. public UserId(int intId, String varcName, String varcAddress, int intAge) {
  26. this.intId = intId;
  27. this.varcName = varcName;
  28. this.varcAddress = varcAddress;
  29. this.intAge = intAge;
  30. }
  31. // Property accessors
  32. @Column (name = "intId", nullable = false)
  33. public int getIntId() {
  34. return this.intId;
  35. }
  36. public void setIntId(int intId) {
  37. this.intId = intId;
  38. }
  39. @Column (name = "varcName", length = 50)
  40. public String getVarcName() {
  41. return this.varcName;
  42. }
  43. public void setVarcName(String varcName) {
  44. this.varcName = varcName;
  45. }
  46. @Column (name = "varcAddress", length = 50)
  47. public String getVarcAddress() {
  48. return this.varcAddress;
  49. }
  50. public void setVarcAddress(String varcAddress) {
  51. this.varcAddress = varcAddress;
  52. }
  53. @Column (name = "intAge", nullable = false)
  54. public int getIntAge() {
  55. return this.intAge;
  56. }
  57. public void setIntAge(int intAge) {
  58. this.intAge = intAge;
  59. }
  60. public boolean equals(Object other) {
  61. if ((this == other))
  62. return true;
  63. if ((other == null))
  64. return false;
  65. if (!(other instanceof UserId))
  66. return false;
  67. UserId castOther = (UserId) other;
  68. return (this.getIntId() == castOther.getIntId())
  69. && ((this.getVarcName() == castOther.getVarcName()) || (this.getVarcName() != null
  70. && castOther.getVarcName() != null && this.getVarcName().equals(castOther.getVarcName())))
  71. && ((this.getVarcAddress() == castOther.getVarcAddress()) || (this.getVarcAddress() != null
  72. && castOther.getVarcAddress() != null && this.getVarcAddress().equals(
  73. castOther.getVarcAddress()))) && (this.getIntAge() == castOther.getIntAge());
  74. }
  75. public int hashCode() {
  76. int result = 17;
  77. result = 37 * result + this.getIntId();
  78. result = 37 * result + (getVarcName() == null ? 0 : this.getVarcName().hashCode());
  79. result = 37 * result + (getVarcAddress() == null ? 0 : this.getVarcAddress().hashCode());
  80. result = 37 * result + this.getIntAge();
  81. return result;
  82. }
  83. }</span>
package com.sourcefour.bean;

// default package

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

/**
 * UserId entity. @author  MyEclipse Persistence Tools
 */
@Embeddable
public class UserId implements java.io.Serializable {

	// Fields

	private int intId;
	private String varcName;
	private String varcAddress;
	private int intAge;

	// Constructors

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

	/** minimal constructor */
	public UserId(int intId, int intAge) {
		this.intId = intId;
		this.intAge = intAge;
	}

	/** full constructor */
	public UserId(int intId, String varcName, String varcAddress, int intAge) {
		this.intId = intId;
		this.varcName = varcName;
		this.varcAddress = varcAddress;
		this.intAge = intAge;
	}

	// Property accessors

	@Column(name = "intId", nullable = false)
	public int getIntId() {
		return this.intId;
	}

	public void setIntId(int intId) {
		this.intId = intId;
	}

	@Column(name = "varcName", length = 50)
	public String getVarcName() {
		return this.varcName;
	}

	public void setVarcName(String varcName) {
		this.varcName = varcName;
	}

	@Column(name = "varcAddress", length = 50)
	public String getVarcAddress() {
		return this.varcAddress;
	}

	public void setVarcAddress(String varcAddress) {
		this.varcAddress = varcAddress;
	}

	@Column(name = "intAge", nullable = false)
	public int getIntAge() {
		return this.intAge;
	}

	public void setIntAge(int intAge) {
		this.intAge = intAge;
	}

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

		return (this.getIntId() == castOther.getIntId())
				&& ((this.getVarcName() == castOther.getVarcName()) || (this.getVarcName() != null
						&& castOther.getVarcName() != null && this.getVarcName().equals(castOther.getVarcName())))
				&& ((this.getVarcAddress() == castOther.getVarcAddress()) || (this.getVarcAddress() != null
						&& castOther.getVarcAddress() != null && this.getVarcAddress().equals(
						castOther.getVarcAddress()))) && (this.getIntAge() == castOther.getIntAge());
	}

	public int hashCode() {
		int result = 17;

		result = 37 * result + this.getIntId();
		result = 37 * result + (getVarcName() == null ? 0 : this.getVarcName().hashCode());
		result = 37 * result + (getVarcAddress() == null ? 0 : this.getVarcAddress().hashCode());
		result = 37 * result + this.getIntAge();
		return result;
	}

}


3. 可能还会出现的问题

具体来说问题就是查询出来的结果列表为‘null’(这一点我这次在我机器上测试时没有出现)。
如果出现了该问题,那么看到这一点就应该能解决问题啦,如果不出现那就更好,呵呵!
但是个人觉得这一点应该还是得说的。^_^
有时候查询出来的结果列表为‘null’,这令人很是费解,可以想下这是什么原因?
直接上原因,嘎嘎……。
原因:作为联合主键的字段理论上不应该包含可能为空的字段。
原因分析:根据原因,说明实体Bean中的某个(些)对应的表字段有空值。
解决方案:只需要将可能为空的字段不作为联合主键的一部分就可以。
说的估计晕头了吧,直接来个事例吧(个人一直觉得,例子是解释问题的最好说明)。

假设表中的varcName和varcAddress是可能为空的,其它都不可能为空,那么映射应该是这样的

User.java

  1. ……
  2. private UserId id;
  3. private String varcName;
  4. private String varcAddress;
  5. ……
  6. /*
  7. 这里加入varcName和varcAddress映射内容,嗯还是贴出来吧,反正电子档的又不怕木有地方,嘎嘎……
  8. */
  9. @Column (name="varcName", length=50)
  10. public String getVarcName() {
  11. return this.varcName;
  12. }
  13. public void setVarcName(String varcName) {
  14. this.varcName = varcName;
  15. }
  16. @Column (name="varcAddress", length=50)
  17. public String getVarcAddress() {
  18. return this.varcAddress;
  19. }
  20. public void setVarcAddress(String varcAddress) {
  21. this.varcAddress = varcAddress;
  22. }
……
private UserId id;
private String varcName;
private String varcAddress;
……
/*
这里加入varcName和varcAddress映射内容,嗯还是贴出来吧,反正电子档的又不怕木有地方,嘎嘎……
*/
	@Column(name="varcName", length=50)
    public String getVarcName() {
        return this.varcName;
    }
    
    public void setVarcName(String varcName) {
        this.varcName = varcName;
    }

    @Column(name="varcAddress", length=50)
    public String getVarcAddress() {
        return this.varcAddress;
    }
    
    public void setVarcAddress(String varcAddress) {
        this.varcAddress = varcAddress;
    }


UserId.java

  1. ……
  2. private int intId;
  3. private int intAge;
  4. ……

转载于:https://my.oschina.net/jie07/blog/73839

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值