孫衛琴的《精通JPA與Hibernate》的讀書筆記:映射對象標識符的基本原理

Java語言按內存地址來識別或區分同一個類的不一樣對象,而關係數據庫按主鍵值來識別或區分同一個表的不一樣記錄。Hibernate使用OID來統一二者之間的矛盾,OID是關係數據庫中的主鍵(一般爲代理主鍵)在Java對象模型中的等價物。java

在運行時,Hibernate根據OID來維持Java對象和數據庫表中記錄的對應關係。例如:數據庫

Transaction tx = session.beginTransaction();  
Customer c1=session.get(Customer.class, Long.valueOf(1));  
Customer c2=session.get(Customer.class, Long.valueOf(1));  
Customer c3=session.get(Customer.class, Long.valueOf(3));  
System.out.println(c1==c2);  
System.out.println(c1==c3);  

tx.commit();

在以上程序中,三次調用了Session的get()方法,分別加載OID爲1或3的Customer對象。如下是Hibernate三次加載Customer對象的流程:緩存

  • (1)第一次加載OID爲1的Customer對象時,先從數據庫的CUSTOMERS表中查詢ID爲1的記錄,再建立相應的Customer實例,把它保存在Session緩存中,最後把這個對象的引用賦值給變量c1。
  • (2)第二次加載OID爲1的Customer對象時,直接把Session緩存中OID爲1的Customer對象的引用賦值給c2,所以c1和c2引用同一個Customer對象。
  • (3)當加載OID爲3的Customer對象時,因爲在Session緩存中還不存在這樣的對象,因此必須再次到數據庫中查詢ID爲3的記錄,再建立相應的Customer實例,把它保存在Session緩存中,最後把這個對象的引用賦值給變量c3。

所以,表達式c1== c2的結果爲true,表達式c1==c3的結果爲false。markdown

與表的代理主鍵對應,OID也是整數類型,Hibernate容許在持久化類中把與代理主鍵對應的OID定義爲如下類型:session

  • short(或包裝類Short):2個字節,取值範圍是:-2^15 ~ 2^15-1
  • int(或包裝類Integer):4個字節,取值範圍是:-2^31 ~ 2^31-1
  • long(或包裝類Long):8個字節,取值範圍是:-2^63 ~ 2^63-1
  • java.math.BigInteger類:大整數類型。
  • java.math.BigDecimal類:大浮點數類型。儘管它是浮點數,實際上Hibernate的內置標識符生成器仍然按照整數遞增的方式爲OID賦值。

爲了保證持久化對象的OID的惟一性和不可變性,一般由Hibernate或底層數據庫來給OID賦值。所以,能夠把持久化類的OID的setId()方法設爲private類型,以禁止Java應用程序隨便修改OID。而把getId()方法設爲public 類型,這使得Java應用程序能夠讀取持久化對象的OID:ide

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

在持久化類中,用來自JPA API的@Id註解和@GeneratedValue註解來映射對象標識符,例如:ui

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ID")
private Long id;

以上@Id註解代表id屬性是OID,@GeneratedValue註解設定如何爲OID賦值,它的strategy屬性指定標識符生成策略。JPA API經過GenerationType枚舉類型定義了四種標識符生成策略:this

  • GenerationType.AUTO:根據標識符的數據類型以及數據庫對自動生成標識符的支持方式,來選擇具體的標識符生成器,如identity、uuid或sequence等。
  • GenerationType.IDENTITY:由數據庫自動生成標識符。
  • GenerationType.SEQUENCE:由數據庫中的特定序列來生成標識符。
  • GenerationType.TABLE:由用戶自定義的表來生成標識符。

對於以上標識符生成策略,Hibernate會經過相應的標識符生成器來實現這些標識符生成策略。例如如下代碼經過@SequenceGenerator註解設置了具體的序列化標識符生成器:atom

@Id
  @GeneratedValue(
    strategy = GenerationType.SEQUENCE,
    generator = "sequence-generator"
  )
  @SequenceGenerator(  //具體的序列化標識符生成器
    name = "sequence-generator",
    sequenceName = "hibernate_sequence"
  )
  @Column(name="ID") 
  private Long id;

在這裏插入圖片描述

相關文章
相關標籤/搜索