首頁 > 軟體

使用JPA主鍵@Id,@IdClass,@Embeddable,@EmbeddedId問題

2022-06-13 14:01:52

JPA主鍵@Id,@IdClass,@Embeddable,@EmbeddedId

1、自動主鍵

預設情況下,主鍵是一個連續的64位元數位(long),它由ObjectDB自動為儲存在資料庫中的每個新實體物件自動設定。

資料庫中的第一個實體物件的主鍵是1,第二個實體物件的主鍵是2等等。

當從資料庫中刪除實體物件時,主鍵值不會被回收。

一個實體的主鍵值可以通過宣告一個主鍵欄位來存取:

@Entity
public class Project {
    @Id @GeneratedValue long id; // still set automatically
}
  • @id標註將欄位標記為一個主鍵欄位。當定義主鍵欄位時,主鍵值將被ObjectDB自動注入到該欄位中。
  • @generatedvalue註釋指定主鍵是由ObjectDB自動分配的

2、應用設定主鍵

如果一個實體有一個沒有@generatedvalue標記的主鍵欄位,則不會生成自動主鍵值,並且應用程式負責通過初始化主鍵欄位來設定主鍵。這必須在持久化實體物件的任何嘗試之前完成。

@Entity
public class Project {
    @Id long id; // must be initialized by the application
}

應用程式設定的主鍵欄位可以有以下型別:

 ● 原始型別: boolean, byte, short, char, int, long, float, double.

 ● java.lang包中的包裝型別:Byte, Short, Character, Integer, Long, Float, Double.

 ● java.math.BigInteger, java.math.BigDecimal.

 ● java.lang.String.

 ● java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp.

 ● 列舉型別

● 參照一個實體物件

3、複合主鍵

複合主鍵由多個主鍵欄位組成。每個主鍵欄位必須是上面列出的支援型別之一。

例如,以下專案實體類的主鍵由兩個欄位組成:

@Entity @IdClass(ProjectId.class)
public class Project {
    @Id int departmentId;
    @Id long projectId;
}

當一個實體有多個主鍵欄位時,JPA需要定義一個特殊的ID類,該類是使用@idclass註釋附加到實體類的。ID類反映了主鍵欄位,它的物件可以表示主鍵值:

Class ProjectId {
    int departmentId;
    long projectId;
}

ObjectDB不強制定義ID類。但是,如果實體物件必須按照檢索實體部分中所示的主鍵來檢索實體物件,那麼就需要ID類。

4、嵌入式主鍵

表示複合主鍵的另一種方法是使用可嵌入的類:

@Entity
public class Project {
    @EmbeddedId ProjectId id;
}
@Embeddable
Class ProjectId {
    int departmentId;
    long projectId;
}

主鍵欄位是在可嵌入類中定義的。

該實體包含一個單獨的主鍵欄位,該欄位用@EmbeddedId 註釋,幷包含一個可嵌入類的範例。

當使用這個表單時,沒有定義一個單獨的ID類,因為可嵌入的類本身可以表示完整的主鍵值。

@EmbeddedId和@IdClass的區別

@idClass

使複合主鍵類成為非嵌入類,使用 @IdClass 批註為實體指定一個複合主鍵類(通常由兩個或更多基元型別或 JDK 物件型別組成)。從原有資料庫對映時(此時資料庫鍵由多列組成),通常將出現複合主鍵。

複合主鍵類具有下列特徵:

  • 它是一個普通的舊式 Java 物件 (POJO) 類。
  • 它必須為 public,並且必須有一個 public 無引數建構函式。
  • 如果使用基於屬性的存取,則主鍵類的屬性必須為 public 或 protected。
  • 它必須是可序列化的。
  • 它必須定義 equals 和 hashCode 方法。
  • 這些方法的值相等性的語意必須與鍵對映到的資料庫型別的資料庫相等性一致。
  • 它的欄位或屬性的型別和名稱必須與使用 @Id 進行批註的實體主鍵欄位或屬性的型別和名稱相對應。
package com.model;
import java.io.Serializable;
public class SysUserRoleId implements Serializable{ 
    /**
     *
     */
    private static final long serialVersionUID = 2606793267849167078L;
    private Long userId;
    private Long roleId;
     
    @Override
    public int hashCode(){
        int result = 1;
        result = userId.hashCode()+roleId.hashCode();
        return result;
    }
     
    @Override
    public boolean equals(Object obj){
    
        if(obj == null){
            return false;
        }
         
        if(this == obj){
            return true;
        }
         
        if(getClass() != obj.getClass()){
            return false;
        }
         
        final SysUserRoleId other = (SysUserRoleId) obj;
        if(other.getUserId().equals(this.userId) && other.getRoleId().equals(this.roleId)){
            return true;
        }
         
        return false;
    }
     
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    public Long getRoleId() {
        return roleId;
    }
    public void setRoleId(Long roleId) {
        this.roleId = roleId;
    }  
}
package com.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
  
@Entity
@Table(name="SYS_USER_ROLE")
@IdClass(SysUserRoleId.class)
public class SysUserRole {
    private Long userId;
    private Long roleId;
    public SysUserRole(){ 
    }
     
    public SysUserRole(Long userId,Long roleId){
        this.userId = userId;
        this.roleId = roleId;
    }
     
    @Id
    @Column(name="user_id")
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
     
    @Id
    @Column(name="role_id")
    public Long getRoleId() {
        return roleId;
    }
    public void setRoleId(Long roleId) {
        this.roleId = roleId;
    }    
}

@EmbeddedId

使複合主鍵類成為由實體擁有的嵌入類

使用 @EmbeddedId 批註指定一個由實體擁有的可嵌入複合主鍵類(通常由兩個或更多基元型別或 JDK 物件型別組成)。從原有資料庫對映時(此時資料庫鍵由多列組成),通常將出現複合主鍵。

複合主鍵類具有下列特徵:

  • 它是一個普通的舊式 Java 物件 (POJO) 類。
  • 它必須為 public,並且必須有一個 public 無引數建構函式。
  • 如果使用基於屬性的存取,則主鍵類的屬性必須為 public 或 protected。
  • 它必須是可序列化的。
  • 它必須定義 equals 和 hashCode 方法。
  • 這些方法的值相等性的語意必須與鍵對映到的資料庫型別的資料庫相等性一致。
package com.model;
import java.io.Serializable;
import javax.persistence.Column;
@SuppressWarnings("serial")
public class SysOrganizationRolePKId implements Serializable{
    private Long organizationId;
    private Long roleId;
     
    @Column(name="organization_id")
    public Long getOrganizationId() {
        return organizationId;
    }
    public void setOrganizationId(Long organizationId) {
        this.organizationId = organizationId;
    }
     
    @Column(name="role_id")
    public Long getRoleId() {
        return roleId;
    }
    public void setRoleId(Long roleId) {
        this.roleId = roleId;
    }     
}
package com.model;
import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
 
@Entity
@SuppressWarnings("serial")
@Table(name="SYS_ORGANIZATION_ROLE")
public class SysOrganizationRole implements Serializable{
    private SysOrganizationRolePKId sysOrganizationRolePKId;
 
    @EmbeddedId
    public SysOrganizationRolePKId getSysOrganizationRolePKId() {
        return sysOrganizationRolePKId;
    }
 
    public void setSysOrganizationRolePKId(
            SysOrganizationRolePKId sysOrganizationRolePKId) {
        this.sysOrganizationRolePKId = sysOrganizationRolePKId;
    }   
}

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com