hibernate 复合主键 注解
2017-02-16 00:19
260 查看
Hibernate注解规范的文档中提供了三种方法:
1. 将组件类注解为@Embeddable,并将组件的属性注解为@Id;
主类
package com.cmh.beans;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* Created by mianhai on 2017/2/16.
*/
@Entity
@Table
public class EmbeddableTest {
@EmbeddedId
private TestPK id;
}
这里需要注意的是在实体类中同时还要写上复合主键的字段比如@Column(name = “lastname”)和
@Column(name = “firstname”)
不想在TestPK中定义列名,可以用以下方法,用于公共复合主键
通过@AttributeOverride注释来指定Test类的firstName,lastName与数据库中表的first_name,last_name进行映射.
以下代码在class Test
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name = firstName, column = @Column(name = first_name)),
@AttributeOverride(name = lastName, column = @Column(name = last_name)) })
将类注解为@IdClass,并将该实体中所有主键属性注解为@Id。
这里,我采用的是第三种方法——@IdClass,下面就是具体的代码,大家一块讨论一下。
首先,需要说明的是,采用@IdClass方式,需要根据所有的主键属性,建立一个主键类,该主键类包含所有的主键,而且,作为主键类,需要满足以下要求:
主键类必须实现序列化接口(implements Serializable);
主键类必须有默认的public无参数的构造方法;
主键类必须覆盖equals和hashCode方法。
代码如下:
我们的PK
主类
生成的sql如下:
在主键类中,为了能使集合框架中的类(如HashMap)正常工作,必须同时覆盖equals和hashCode方法,而且不要由于写错参数类型,而重载了这个方法,却没有覆盖它们。
覆盖equals时总要覆盖hashCode,一个很常见的错误根源在没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,这样的集合包括HashMap、HashSet和Hashtable。
——摘自《Effective Java》
1. 将组件类注解为@Embeddable,并将组件的属性注解为@Id;
2. 将组件的属性注解为@Embeddable;
package com.cmh.beans; import javax.persistence.Embeddable; import java.io.Serializable; @Embeddable public class TestPK implements Serializable { private static final long serialVersionUID = 7935499208104916305L; private String firstName; private String lastName; public TestPK() { } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @Override public boolean equals(Object obj) { if(this == obj) return true; if(obj == null) return false; if(!(obj instanceof TestKey)) return false; TestPK objKey = (TestPK)obj; if(firstName.equalsIgnoreCase(objKey.firstName) && lastName.equalsIgnoreCase(objKey.lastName)) { return true; } return false; } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + (firstName == null ? 0 : firstName.hashCode()); result = PRIME * result + (lastName == null ? 0 : lastName.hashCode()); return result; } }
主类
package com.cmh.beans;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* Created by mianhai on 2017/2/16.
*/
@Entity
@Table
public class EmbeddableTest {
@EmbeddedId
private TestPK id;
private String name; public EmbeddableTest() { } @Column(name = "firstname") public String getFirstName(){ return id.getFirstName(); } @Column(name = "lastname") public String getLastName(){ return id.getLastName(); } @Column(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; }
}
这里需要注意的是在实体类中同时还要写上复合主键的字段比如@Column(name = “lastname”)和
@Column(name = “firstname”)
不想在TestPK中定义列名,可以用以下方法,用于公共复合主键
通过@AttributeOverride注释来指定Test类的firstName,lastName与数据库中表的first_name,last_name进行映射.
以下代码在class Test
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name = firstName, column = @Column(name = first_name)),
@AttributeOverride(name = lastName, column = @Column(name = last_name)) })
将类注解为@IdClass,并将该实体中所有主键属性注解为@Id。
这里,我采用的是第三种方法——@IdClass,下面就是具体的代码,大家一块讨论一下。
首先,需要说明的是,采用@IdClass方式,需要根据所有的主键属性,建立一个主键类,该主键类包含所有的主键,而且,作为主键类,需要满足以下要求:
主键类必须实现序列化接口(implements Serializable);
主键类必须有默认的public无参数的构造方法;
主键类必须覆盖equals和hashCode方法。
代码如下:
我们的PK
package com.cmh.beans; import java.io.Serializable; /** * Created by mianhai on 2017/2/15. */ public class TestKey implements Serializable{ private static final long serialVersionUID = 6811601262303871530L; // 主键属性 private String ip; // 主键属性 private String examPlaceId; // 主键属性 private String examId; /** * 无参数的public构造方法,必须要有 */ public TestKey() { } /** * 重写了一个带参数的构造方法 * @param ip * @param examPlaceId * @param examId */ public TestKey(String ip, String examPlaceId, String examId) { this.ip = ip; this.examId = examId; this.examPlaceId = examPlaceId; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getExamPlaceId() { return examPlaceId; } public void setExamPlaceId(String examPlaceId) { this.examPlaceId = examPlaceId; } public String getExamId() { return examId; } public void setExamId(String examId) { this.examId = examId; } public static long getSerialversionuid() { return serialVersionUID; } /** * 覆盖hashCode方法,必须要有 */ @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + (ip == null ? 0 : ip.hashCode()); result = PRIME * result + (examId == null ? 0 : examId.hashCode()); result = PRIME * result + (examPlaceId ==null ? 0 : examPlaceId.hashCode()); return result; } /** * 覆盖equals方法,必须要有 */ @Override public boolean equals(Object obj) { if(this == obj) return true; if(obj == null) return false; if(!(obj instanceof TestKey)) return false; TestKey objKey = (TestKey)obj; if(ip.equalsIgnoreCase(objKey.ip) && examId.equalsIgnoreCase(objKey.examId) && examPlaceId.equalsIgnoreCase(objKey.examPlaceId)) { return true; } return false; } }
主类
package com.cmh.beans; import javax.persistence.*; /** * Created by mianhai on 2017/2/15. */ @Entity @Table(name="TE_IPMap") @IdClass(TestKey.class) public class ComponetIDKey { // 主键,这里需要添加@Id标记 @Id @Column(name="IP") private String ip; @Column(name="StudentNo") private String studentNo; // 主键,这里需要添加@Id标记 @Id @Column(name="ExamPlaceId") private String examPlaceId; // 主键,这里需要添加@Id标记 @Id @Column(name="ExamId", unique=true) private String examId; public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getStudentNo() { return studentNo; } public void setStudentNo(String studentNo) { this.studentNo = studentNo; } public String getExamPlaceId() { return examPlaceId; } public void setExamPlaceId(String examPlaceId) { this.examPlaceId = examPlaceId; } public String getExamId() { return examId; } public void setExamId(String examId) { this.examId = examId; } }
生成的sql如下:
create table te_ipmap (exam_id varchar(255) not null, exam_place_id varchar(255) not null, ip varchar(255) not null, student_no varchar(255), primary key (exam_id, exam_place_id, ip))
在主键类中,为了能使集合框架中的类(如HashMap)正常工作,必须同时覆盖equals和hashCode方法,而且不要由于写错参数类型,而重载了这个方法,却没有覆盖它们。
覆盖equals时总要覆盖hashCode,一个很常见的错误根源在没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,这样的集合包括HashMap、HashSet和Hashtable。
——摘自《Effective Java》
相关文章推荐
- hibernate注解方式实现复合主键
- Hibernate复合主键的注解
- hibernate注解方式实现复合主键
- hibernate注解方式实现复合主键
- Hibernate复合主键(注解)操作分区数据表
- hibernate 注解 生成复合主键
- Hibernate 联合/复合主键注解方法
- Hibernate复合主键的注解
- Hibernate复合主键的注解
- hibernate注解方式实现复合主键
- hibernate联合主键 注解方式
- Hibernate 学习笔记( 三)-- 复合主键
- Hibernate中的复合主键映射(了解)
- 联合主键用Hibernate注解映射的三种方式
- hibernate注解UUID主键生成策略
- Hibernate中复合主键的配置
- Hibernate注解实现复杂主键(多主键,外键当主键,主键自动生成,普通主键)
- hibernate 复合主键
- Hibernate---->component映射和复合主键映射
- hibernate联合主键 注解方式