ID生成策略(一)
ID生成策略:主鍵手工設定很不方便,在我們實際工作中在MySQL里面用自增字段auto increment,在oracel中一般用sequence。所以把表建成auto increment,對于類里面對象的對應的值就不能指定了,得靠程序或數據庫自動生成,hibernate或JPA就實現了這樣的功能,我們可以通過設置告訴這個字段怎么生成,這樣寫程序的時候就不用設定了。這個就叫ID的生成策略。
?
動手實驗:
使用xml時,常用<generator class="native"></generator>
native根據底層數據庫的能力選擇identity, sequence 或者hilo中的一個。
對DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的內置標識字段提供支持。 返回的標識符是long, short 或者int類型的。
在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的標識符是long, short或者 int類型的。
?使用annotation,使用注解@GeneratedValue默認值是auto相當于xml里面的native?
@SequenceGenerator(name="teacherSEQ", sequenceName="teacherSEQ_DB")
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@TableGenerator
聯合主鍵:假設sutdent的id和name是它的主鍵。單獨寫一個類作為學生的主鍵類StudentPK.java,在主鍵類里面必須要重寫equals、hashCode方法,實現serializable接口(為什么?),serializable把當前對象序列化,這樣就可以直接寫到硬盤上,也可以直接讀出來,也可以直接傳送。為什么要序列化呢?作為Student這個對象來說,它在數據庫表里可能存在多條記錄,如果把這多條記錄放到內存里就是多個Student對象,每個對象都有一個主鍵StudentPK對象。系統做集群,好多個服務器,如果這臺服務器當機了,可以把這臺服務器里的對象傳給另外一臺服務器,就需要實現序列化,但是這種情況并不多見。還有一種情況,加入內存滿了,可以使用虛擬內存(把硬盤上一塊空間作為內存使用)。這種情況下就可以把序列化了的那一部分內容先暫時放到硬盤上去。主鍵類為什么要重寫equals和hashCode呢?是為了保證唯一性,不僅 在數據庫中保證唯一性,我們還要把數據放到內存中,好多student對象,里面都有自己的studentpK,那么每個對象之間怎么區分開來?數據庫里面用主鍵做區分,那么內存里面也應該用這種邏輯來做區分,不然和數據庫內容就不匹配了,所以用聯合主鍵就應該重寫equals和hashCode。從數據庫的角度想,主鍵相同就返回true,從內存角度想主鍵相同就是id和name相同。為什么重寫hashCode呢?如果我們的對象裝到了hash表里面,查找里面的對象,首先是查找hashcode。所以最終代碼如下:
package hjj.lch.hibernate.model;import java.io.Serializable;public class StudentPK implements Serializable{private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic boolean equals(Object obj){if(obj instanceof StudentPK){StudentPK pk = (StudentPK)obj;if(this.id == pk.getId() && this.name.equals(pk.getName())){return true;}}return false;}@Overridepublic int hashCode(){return this.name.hashCode();} }?
在Student.java里面就不用寫id和name了,但是需要記錄一個主鍵類的對象,這樣才能唯一的記錄當前的student。
package hjj.lch.hibernate.model;public class Student {private StudentPK pk;private int age; // 年齡public StudentPK getPk() {return pk;}public void setPk(StudentPK pk) {this.pk = pk;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
配置文件里面表名主鍵,組件作為聯合標志符
一開始利用HibernateExportUtil在控制臺生成的建表語句在Mysql Commend Client中執行,會出現以下錯誤
Specified key was too long; max key length is 767 bytes。意思就是主鍵太長了.解決辦法在student.hbm.xml文件中設置那兩個字段的長度,所以加了length="16"。
?
下面說annotation的聯合主鍵用法,將主鍵類TeacherPK.java注為@Embeddable,并且把主鍵的屬性注解為@Id
package hjj.lch.hibernate.model;import java.io.Serializable;import javax.persistence.Column; import javax.persistence.Embeddable;@Embeddable public class TeacherPK implements Serializable{private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}@Column(name="name", length=16)public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic boolean equals(Object obj){if(obj instanceof TeacherPK){TeacherPK pk = (TeacherPK)obj;if(this.id == pk.getId() && this.name.equals(pk.getName()));return true;}return false;}@Overridepublic int hashCode(){return this.name.hashCode();}}報錯Specified key was too long; max key length is 767 bytes的時候限制字段長度就好, @Column(name="name", length=16)。
?
package hjj.lch.hibernate.model;import javax.persistence.Entity; import javax.persistence.Id;@Entity public class Teacher {private TeacherPK pk;private String title; // 職稱 @Idpublic TeacherPK getPk() {return pk;}public void setPk(TeacherPK pk) {this.pk = pk;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;} }這是第一種方法,下面做第二種方法是在Teacher.java中將teacherpk組件注解為@EmbeddedId。TeacherPK.java中就不用注解了
package hjj.lch.hibernate.model;import java.io.Serializable;import javax.persistence.Column;public class TeacherPK implements Serializable{private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}@Column(name="name", length=16)public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic boolean equals(Object obj){if(obj instanceof TeacherPK){TeacherPK pk = (TeacherPK)obj;if(this.id == pk.getId() && this.name.equals(pk.getName()));return true;}return false;}@Overridepublic int hashCode(){return this.name.hashCode();}} package hjj.lch.hibernate.model;import javax.persistence.EmbeddedId; import javax.persistence.Entity;@Entity public class Teacher {private TeacherPK pk;private String title; // 職稱 @EmbeddedIdpublic TeacherPK getPk() {return pk;}public void setPk(TeacherPK pk) {this.pk = pk;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;} }?
再做第三種將類注解為@IdClass,并將該實體類中所有屬于主鍵的屬性都注解為@Id,TeacherPK.java里面就不用寫那些了。
package hjj.lch.hibernate.model;import java.io.Serializable;import javax.persistence.Column;public class TeacherPK implements Serializable{private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}@Column(name="name", length=16)public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic boolean equals(Object obj){if(obj instanceof TeacherPK){TeacherPK pk = (TeacherPK)obj;if(this.id == pk.getId() && this.name.equals(pk.getName()));return true;}return false;}@Overridepublic int hashCode(){return this.name.hashCode();}}?
package hjj.lch.hibernate.model;import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass;@Entity @IdClass(TeacherPK.class) public class Teacher {private int id;private String name;private String title; // 職稱 @Idpublic int getId() {return id;}public void setId(int id) {this.id = id;}@Idpublic String getName() {return name;}public void setName(String name) {this.name = name;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;} }?
第二種和第三種比較常用,但是聯合主鍵就不常用!!!哈哈
?
?
?
?
?
轉載于:https://www.cnblogs.com/ligui989/p/3454230.html
總結
- 上一篇: C#图片上一张下一张
- 下一篇: java replaceall函数_JA