主鍵問題

因爲在Oracle數據庫中,容許沒有主鍵的存在,而hibernate體系又不容許沒有主鍵,這在邏輯上是有衝突的。事實上,表不須要主鍵。表沒有顯式鍵對數據庫沒有任何影響,由於數據庫中的每一行都有一個隱式的惟一數據點,Oracle將其用於存儲和某些內部引用,即rowid僞列。rowid是惟一標識數據庫中每一行的一段數據。嚴格來講,沒有必要把鑰匙放在桌子上。好比如今的項目中,使用的oracle10g數據庫有超過1000個系統表,它們沒有主鍵或者說在各自的表上有惟一鍵。dba和開發人員均可以決定如何在數據庫表上建立密鑰。然而在開發過程當中老是建立主鍵,這個估計是開發框架致使的,而框架才無論它們是否有用或健全。但做爲優秀dba,他們只在有意義的地方建立鍵。
不少時候線上和線下開發是徹底隔離開的,線下開發後的測試環境也不可能那麼完美的貼合生產環境,筆者的項目中所使用數據庫爲marridb,而生產環境中使用的數據庫爲Oracle,這個聯調過程當中產生的bug也真的是不可多得:),我這邊獲取到測試數據確實是來自生產環境,然而這個是經過select語句而來的,這就直接致使這個表是沒有主鍵的。以後把這些測試數據導入到marridb。java

如今的狀況就是數據庫一個沒有主鍵的表,然而經過springboot所建立實體卻要求配置主鍵,這跟數據庫中的配置不相符,此外因爲實體類中所定義的主鍵,在數據庫中重複出現。spring

主鍵問題

這其實是違背了數據庫中主鍵的定義惟一地標識表中的每一行,經過它可強制表的實體完整性,致使出現這樣表的緣由是,在Oracle中容許沒有主鍵的定義,經過多表聯查彙總到一張表中,而後將這張表導入到marridb中,纔會出現這麼尷尬的結果數據庫

主鍵問題

致使的結果就是搜索到某一個uuid,其結果有17條,經過jpa取結果整個list長度確實爲17,然而,數據展開以後會發現,裏面幾乎都是重複數據express

2019-12-09 19:39:20.411  WARN 26340 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bussiness' defined in file [/xxx/yyy/zzz/service/Bussiness.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'alarmStatisticServiceImpl' defined in file [xxx/yyy/zzz/service/impl/AlarmStatisticServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processAccountRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List xxx.yyy.zzz.repository.ProcessAccountRepository.getAllData()!

沒法建立一個bean,而其實是因爲某一類是未指定標識符的實體,主要緣由是hibernate在進行掃描實體的時候,未發現其主鍵標識。因此就在其類上添加主鍵標識。由於個人這個類比較特殊,須要添加聯合主鍵springboot

聯合主鍵用Hibernate註解映射方式主要有三種:oracle

  1. 將聯合主鍵的字段單獨放在一個類中,該類須要實現java.io.Serializable接口並重寫equals和hascode,再將該類註解爲@Embeddable,最後在主類中(該類不包含聯合主鍵類中的字段)保存該聯合主鍵類的一個引用,並生成set和get方法,以後將該引用註解爲@Id
  框架

@Entity
@Table(name = "Process_Account")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ProcessAccount {

    @Id
    private ProcessAccountPk priAccountpk;
}

  
主鍵類:  ide

@Embeddable
public class ProcessAccountPk implements Serializable {
    @Column(name = "UUID")
    private String uuid;

    @Column(name = "xxx")
    private String priAccount;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ProcessAccountPk)) return false;
        ProcessAccountPk that = (ProcessAccountPk) o;
        return Objects.equals(getUuid(), that.getUuid()) &&
            Objects.equals(getPriAccount(), that.getPriAccount());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getUuid(), getPriAccount());
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getPriAccount() {
        return priAccount;
    }

    public void setPriAccount(String priAccount) {
        this.priAccount = priAccount;
    }
}
  1. 將聯合主鍵的字段單獨放在一個類中,該類須要實現java.io.Serializable接口並重寫equals和hascode,最後在主類中(該類不包含聯合主鍵類中的字段)保存該聯合主鍵類的一個引用,並生成set和get方法,並將該引用註解爲@EmbeddedId
@Entity  
@Table(name="Process_Account")  
public class ProcessAccount {  

    @Id
    @Column(name = "RESUUID")
    private String uuid;

    @Id
    @Column(name = "xxx")
    private String priAccount; 
    @EmbeddedId
    private ProcessAccountPk processAccountPk ;
}

  這個時候ProcessAccountPk爲普通Java類便可。測試

  3、將聯合主鍵的字段單獨放在一個類中,該類須要實現java.io.Serializable接口並要重寫equals和hashcode.最後在主類中(該類包含聯合主鍵類中的字段)將聯合主鍵字段都註解爲@Id,並在該類上方將上這樣的註解:@IdClass(聯合主鍵類.class),通過踩坑,我用了這個方法:),中間的判斷過程就一筆帶過吧,有問題私聊ui

@Entity
@Table(name = "Process_Account")
@IdClass(ProcessAccountPk.class)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ProcessAccount {

    @Id
    @Column(name = "RESUUID")
    private String uuid;

    @Id
    @Column(name = "xxx")
    private String priAccount;
}

ProcessAccountPk 繼承自Serializable類

public class ProcessAccountPk implements Serializable {

    private String uuid;

    private String priAccount;

    public ProcessAccountPk() {
    }

    public ProcessAccountPk(String uuid, String priAccount) {
        this.uuid = uuid;
        this.priAccount = priAccount;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ProcessAccountPk)) return false;
        ProcessAccountPk that = (ProcessAccountPk) o;
        return Objects.equals(getUuid(), that.getUuid()) &&
            Objects.equals(getPriAccount(), that.getPriAccount());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getUuid(), getPriAccount());
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getPriAccount() {
        return priAccount;
    }

    public void setPriAccount(String priAccount) {
        this.priAccount = priAccount;
    }
}

主鍵問題

主鍵問題

至此,問題解決了,我取出來的數據不會因爲uuid或者bussinessName致使數據重複,兩個字段同時做爲主鍵進行查詢就能夠解決這個問題

相關文章
相關標籤/搜索