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 | * @author Michael sun |
4 | */ |
5 | public class UserRolePK implements Serializable { |
6 |
7 | public UserRolePK() { |
8 |
9 | } |
10 |
11 | /** |
12 | * serialVersionUID |
13 | */ |
14 | private static final long serialVersionUID = -4901479789268752591L; |
15 |
16 | /** |
17 | * 用户名 |
18 | */ |
19 | private String userId; |
20 |
21 | /** |
22 | * 角色ID |
23 | */ |
24 | private Integer roleId; |
25 |
26 | /** |
27 | * @return the userId |
28 | */ |
29 | public String getUserId() { |
30 | return userId; |
31 | } |
32 |
33 | /** |
34 | * @return the roleId |
35 | */ |
36 | public Integer getRoleId() { |
37 | return roleId; |
38 | } |
39 |
40 | /** |
41 | * @param pUserId the userId to set |
42 | */ |
43 | public void setUserId(String pUserId) { |
44 | userId = pUserId; |
45 | } |
46 |
47 | /** |
48 | * @param pRoleId the roleId to set |
49 | */ |
50 | public void setRoleId(Integer pRoleId) { |
51 | roleId = pRoleId; |
52 | } |
53 |
54 | /** |
55 | * overrides hashCode() |
56 | * @return int |
57 | */ |
58 | public int hashCode() { |
59 | int result; |
60 | result = userId.hashCode(); |
61 | result = 29 * result + roleId.hashCode(); |
62 | return result; |
63 | } |
64 |
65 | /** |
66 | * overrides equals |
67 | * @see java.lang.Object#equals(java.lang.Object) |
68 | */ |
69 |
70 | public boolean equals(Object obj) { |
71 | if ( this == obj) { |
72 | return true ; |
73 | } |
74 | if ( null == obj) { |
75 | return false ; |
76 | } |
77 | if (!(obj instanceof UserRolePK)) { |
78 | return false ; |
79 | } |
80 |
81 | final UserRolePK pko = (UserRolePK) obj; |
82 | if (!userId.equals(pko.userId)) { |
83 | return false ; |
84 | } |
85 | if ( null == roleId || roleId.intValue() != pko.roleId) { |
86 | return false ; |
87 | } |
88 | return true ; |
89 | } |
90 |
91 | } |
二、通过@IdClass注释在实体中标注复合主键,需要注意:
1.@IdClass标注用于标注实体所使用主键规则的类
2.在实体中同时标注主键的属性。本例中在userId和roleId的getter方法前标注@Id,表示复合主键使用这两个属性
实体代码如下:
1 | /** |
2 | * 用户角色关系表 |
3 | * @author Michael sun |
4 | */ |
5 | @Entity |
6 | @Table (name = "TB_USER_ROLE" ) |
7 | @IdClass (UserRolePK. class ) |
8 | public class UserRole implements Serializable { |
9 |
10 | /** |
11 | * serialVersionUID |
12 | */ |
13 | private static final long serialVersionUID = -8743424029912282776L; |
14 |
15 | /** |
16 | * 用户名 |
17 | */ |
18 | private String userId; |
19 |
20 | /** |
21 | * 角色ID |
22 | */ |
23 | private Integer roleId; |
24 |
25 | /** |
26 | * 创建人 |
27 | */ |
28 | private String createUser; |
29 |
30 | /** |
31 | * @return the userId |
32 | */ |
33 | @Id |
34 | @Column (name = "USER_ID" , nullable = false ) |
35 | public String getUserId() { |
36 | return userId; |
37 | } |
38 |
39 | /** |
40 | * @return the roleId |
41 | */ |
42 | @Id |
43 | @Column (name = "ROLE_ID" , nullable = false ) |
44 | public Integer getRoleId() { |
45 | return roleId; |
46 | } |
47 |
48 | /** |
49 | * @param pUserId the userId to set |
50 | */ |
51 | public void setUserId(String pUserId) { |
52 | userId = pUserId; |
53 | } |
54 |
55 | /** |
56 | * @param pRoleId the roleId to set |
57 | */ |
58 | public void setRoleId(Integer pRoleId) { |
59 | roleId = pRoleId; |
60 | } |
61 |
62 | /** |
63 | * @return the createUser |
64 | */ |
65 | @Column (name = "CREATE_USER" ) |
66 | public String getCreateUser() { |
67 | return createUser; |
68 | } |
69 |
70 | /** |
71 | * @param pCreateUser the createUser to set |
72 | */ |
73 | public void setCreateUser(String pCreateUser) { |
74 | createUser = pCreateUser; |
75 | } |
76 |
77 | } |
复合主键也可以采用嵌入式主键替代,例如上面复合主键修改成嵌入式主键的步骤如下:
一、code一个嵌入式主键的类,类似于上面的复合主键的类,需要注意代码中加 @Column 注释的地方
具体代码如下:
1 | /** |
2 | * 用户角色表的复合主键 |
3 | * @author Michael sun |
4 | */ |
5 | public class UserRolePK implements Serializable { |
6 |
7 | /** |
8 | * UserRolePK |
9 | */ |
10 | public UserRolePK() { |
11 | super (); |
12 | } |
13 |
14 | /** |
15 | * @param userId |
16 | * @param roleId |
17 | */ |
18 | public UserRolePK(String userId, Integer roleId) { |
19 | super (); |
20 | this .userId = userId; |
21 | this .roleId = roleId; |
22 | } |
23 |
24 | /** |
25 | * serialVersionUID |
26 | */ |
27 | private static final long serialVersionUID = -4901479789268752591L; |
28 |
29 | /** |
30 | * 用户名 |
31 | */ |
32 | private String userId; |
33 |
34 | /** |
35 | * 角色ID |
36 | */ |
37 | private Integer roleId; |
38 |
39 | /** |
40 | * @return the userId |
41 | */ |
42 | @Column (name = "USER_ID" , nullable = false ) |
43 | public String getUserId() { |
44 | return userId; |
45 | } |
46 |
47 | /** |
48 | * @return the roleId |
49 | */ |
50 | @Column (name = "ROLE_ID" , nullable = false ) |
51 | public Integer getRoleId() { |
52 | return roleId; |
53 | } |
54 | //其他和上面的复合主键一样 |
55 | } |
二、嵌入式主键实体类的写法需要在复合主键类的get方法加注@EmbeddedId
具体代码如下
1 | /** |
2 | * 用户角色关系表 |
3 | * @author Michael sun |
4 | */ |
5 |
6 | @Entity |
7 | @Table (name = "TB_USER_ROLE" ) |
8 | public class UserRole implements Serializable { |
9 |
10 | /** |
11 | * serialVersionUID |
12 | */ |
13 | private static final long serialVersionUID = -8743424029912282776L; |
14 |
15 | /** |
16 | * 复合主键 |
17 | */ |
18 | @EmbeddedId |
19 | private UserRolePK pk; |
20 |
21 | /** |
22 | * 创建人 |
23 | */ |
24 | private String createUser; |
25 |
26 | /** |
27 | * @return the pk |
28 | */ |
29 | @EmbeddedId |
30 | public UserRolePK getPk() { |
31 | return pk; |
32 | } |
33 |
34 | /** |
35 | * @param pPk the pk to set |
36 | */ |
37 | public void setPk(UserRolePK pPk) { |
38 | pk = pPk; |
39 | } |
40 |
41 | /** |
42 | * @return the createUser |
43 | */ |
44 | @Column (name = "CREATE_USER" ) |
45 | public String getCreateUser() { |
46 | return createUser; |
47 | } |
48 |
49 | /** |
50 | * @param pCreateUser the createUser to set |
51 | */ |
52 | public void setCreateUser(String pCreateUser) { |
53 | createUser = pCreateUser; |
54 | } |
55 |
56 | /** |
57 | * @return the String |
58 | */ |
59 | @Transient |
60 | public String getUserId() { |
61 | return pk.getUserId(); |
62 | } |
63 |
64 | /** |
65 | * @return the mergeFlowId |
66 | */ |
67 | @Transient |
68 | public Integer getRoleId() { |
69 | return pk.getRoleId(); |
70 | } |
71 |
72 | /** |
73 | * @param pUserId the userId to set |
74 | */ |
75 | public void setUserId(String pUserId) { |
76 | this .pk.setUserId(pUserId); |
77 | } |
78 |
79 | /** |
80 | * @param pRoleId the roleId to set |
81 | */ |
82 | public void setRoleId(Integer pRoleId) { |
83 | this .pk.setRoleId(pRoleId); |
84 | } |
85 |
86 | } |
原创文章,转载请注明: 转载自micmiu – 软件开发+生活点滴[ http://www.micmiu.com/ ]
本文链接地址: http://www.micmiu.com/j2ee/hibernate/hibernate3-anno-complex-pk/