Hibernate不断发展,几乎成为Java数据库持久性的事实标准,因为它非常强大、灵活,而且具备了优异的性能。
传统上,Hibernate的配置依赖于外部 XML 文件:数据库映射被定义为一组 XML 映射文件,并且在启动时进行加载。当然创建这些映射有很多方法,可以从已有数据库模式或Java类模型中自动创建,也可以手工创建。无论如何,您最终将获得大量的 Hibernate 映射文件,而且增加了我们的工作步骤。
而现在我们可以借助新的 Hibernate Annotation 库,即可一次性将注释直接嵌入到您的 Java 类中,不再需要映射配置的xml文件,提供了一种强大及灵活的方法来声明持久性映射。
本文主要讲解一下如果通过注释来创建复合主键以及嵌入式主键:
比如系统有用户表(UserAccount) 角色表(Role) 用户角色关系表(UserRole)三张表,用户角色关系表中 userId、roleId 组成复合主键。
一、先code 一个复合主键的类UserRolePK:作为符合主键类,要满足以下几点要求。
1.必须实现Serializable接口。
2.必须有默认的public无参数的构造方法。
3.必须覆盖equals和hashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时,是根据equals的返回值来判断的。只有对象的userId和roleId 值完全相同时或同一个对象时则返回true。否则返回false。hashCode方法返回当前对象的哈希码,生成的hashCode相同的概率越小越好,算法可以进行优化。
具体代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
/** * 用户角色表的复合主键 * @author Michael sun */ public class UserRolePK implements Serializable { public UserRolePK() { } /** * serialVersionUID */ private static final long serialVersionUID = -4901479789268752591L; /** * 用户名 */ private String userId; /** * 角色ID */ private Integer roleId; /** * @return the userId */ public String getUserId() { return userId; } /** * @return the roleId */ public Integer getRoleId() { return roleId; } /** * @param pUserId the userId to set */ public void setUserId(String pUserId) { userId = pUserId; } /** * @param pRoleId the roleId to set */ public void setRoleId(Integer pRoleId) { roleId = pRoleId; } /** * overrides hashCode() * @return int */ public int hashCode() { int result; result = userId.hashCode(); result = 29 * result + roleId.hashCode(); return result; } /** * overrides equals * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { if (this == obj) { return true; } if (null == obj) { return false; } if (!(obj instanceof UserRolePK)) { return false; } final UserRolePK pko = (UserRolePK) obj; if (!userId.equals(pko.userId)) { return false; } if (null == roleId || roleId.intValue() != pko.roleId) { return false; } return true; } } |
二、通过@IdClass注释在实体中标注复合主键,需要注意:
1.@IdClass标注用于标注实体所使用主键规则的类
2.在实体中同时标注主键的属性。本例中在userId和roleId的getter方法前标注@Id,表示复合主键使用这两个属性
实体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
/** * 用户角色关系表 * @author Michael sun */ @Entity @Table(name = "TB_USER_ROLE") @IdClass(UserRolePK.class) public class UserRole implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = -8743424029912282776L; /** * 用户名 */ private String userId; /** * 角色ID */ private Integer roleId; /** * 创建人 */ private String createUser; /** * @return the userId */ @Id @Column(name = "USER_ID", nullable = false) public String getUserId() { return userId; } /** * @return the roleId */ @Id @Column(name = "ROLE_ID", nullable = false) public Integer getRoleId() { return roleId; } /** * @param pUserId the userId to set */ public void setUserId(String pUserId) { userId = pUserId; } /** * @param pRoleId the roleId to set */ public void setRoleId(Integer pRoleId) { roleId = pRoleId; } /** * @return the createUser */ @Column(name = "CREATE_USER") public String getCreateUser() { return createUser; } /** * @param pCreateUser the createUser to set */ public void setCreateUser(String pCreateUser) { createUser = pCreateUser; } } |
复合主键也可以采用嵌入式主键替代,例如上面复合主键修改成嵌入式主键的步骤如下:
一、code一个嵌入式主键的类,类似于上面的复合主键的类,需要注意代码中加 @Column 注释的地方
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
/** * 用户角色表的复合主键 * @author Michael sun */ public class UserRolePK implements Serializable { /** * UserRolePK */ public UserRolePK() { super(); } /** * @param userId * @param roleId */ public UserRolePK(String userId, Integer roleId) { super(); this.userId = userId; this.roleId = roleId; } /** * serialVersionUID */ private static final long serialVersionUID = -4901479789268752591L; /** * 用户名 */ private String userId; /** * 角色ID */ private Integer roleId; /** * @return the userId */ @Column(name = "USER_ID", nullable = false) public String getUserId() { return userId; } /** * @return the roleId */ @Column(name = "ROLE_ID", nullable = false) public Integer getRoleId() { return roleId; } //其他和上面的复合主键一样 } |
二、嵌入式主键实体类的写法需要在复合主键类的get方法加注@EmbeddedId
具体代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
/** * 用户角色关系表 * @author Michael sun */ @Entity @Table(name = "TB_USER_ROLE") public class UserRole implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = -8743424029912282776L; /** * 复合主键 */ @EmbeddedId private UserRolePK pk; /** * 创建人 */ private String createUser; /** * @return the pk */ @EmbeddedId public UserRolePK getPk() { return pk; } /** * @param pPk the pk to set */ public void setPk(UserRolePK pPk) { pk = pPk; } /** * @return the createUser */ @Column(name = "CREATE_USER") public String getCreateUser() { return createUser; } /** * @param pCreateUser the createUser to set */ public void setCreateUser(String pCreateUser) { createUser = pCreateUser; } /** * @return the String */ @Transient public String getUserId() { return pk.getUserId(); } /** * @return the mergeFlowId */ @Transient public Integer getRoleId() { return pk.getRoleId(); } /** * @param pUserId the userId to set */ public void setUserId(String pUserId) { this.pk.setUserId(pUserId); } /** * @param pRoleId the roleId to set */ public void setRoleId(Integer pRoleId) { this.pk.setRoleId(pRoleId); } } |
原创文章,转载请注明: 转载自micmiu – 软件开发+生活点滴[ http://www.micmiu.com/ ]
本文链接地址: http://www.micmiu.com/j2ee/hibernate/hibernate3-anno-complex-pk/
0 条评论。