簡體   English   中英

JPA findBy 方法總是轉到 orElseThrow

[英]JPA findBy method always goes to orElseThrow

這是我們的代碼

private IdentificationMaster validateIdentificationType(String idType) {
    if(!StringUtils.isNotBlank(idType))
        throw new IllegalArgumentException("Invalid idType");

    Optional<IdentificationMaster> op1 = specRepo.findById(idType); //testing purpose

    Optional<IdentificationMaster> op2 = specRepo.findByIdentificationType(idType); //testing purpose

    return specRepo.findById(idType)
            .orElse(specRepo.findByIdentificationType(idType)
                    .orElseThrow(() -> new ResourceNotFoundException("Id Type Not Found " + idType)));
}

對於idType我們期待兩個值,它可以是主鍵 id或其對應的identificationType 表只有兩列ididentificationType 問題是即使op1op2不為空,它也會拋出ResourceNotFoundException 現在如果我像這樣改變我的回報

return specRepo.findByIdentificationType(idType)
            .orElse(specRepo.findById(idType)
                .orElseThrow(() -> new ResourceNotFoundException("Id Type Not Found " + idType)));

它再次拋出相同的異常!

存儲庫

@Repository
public interface IdentificationSpecRepository extends CrudRepository<IdentificationMaster, String>{

    Optional<IdentificationMaster> findByIdentificationType(String identificationType);
}

實體

@Entity
@Table(name = "IDENTIFICATION_MASTER")
public class IdentificationMaster {

    @Id
    @Column(name = "ID")
    private String id;


    @Column(name = "IDENTIFICATION_TYPE", unique = true)
    private String identificationType;

    // getters and setters

}

可能是什么問題呢?

return specRepo.findByIdentificationType(idType)
            .orElse(specRepo.findById(idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

是原因。

Java 非常急切地執行並且總是調用 orElse 方法來准備以防萬一它需要它。

你的執行順序不知何故:

  1. specRepo.findByIdentificationType(idType)
  2. orElse無法執行,因為它的參數尚未評估
  3. specRepo.findById(idType)
  4. .orElseThrow(() -> new ResourceNotFoundException("..."))
  5. 3 和 4 的結果變成了 object o
  6. orElse(o)

而不是使用orElse一個應該更喜歡orElseGet

return specRepo.findByIdentificationType(idType)
            .orElseGet(() -> specRepo.findById(idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

只有在需要時才會調用它。

我們這里有兩種情況:

  1. specRepo返回一個非空的 Optional。
  2. specRepo返回空的 object。

在場景 1 中, idType是一個有效的identificationType因此不是一個id ,所以findById會拋出一個異常。 在場景 2 中, idType不是有效的identificationType ,如果它是合法的id ,則該方法應導致拋出異常。

編輯:

雖然這個答案可以診斷問題並描述這種行為的原因是什么, @Abinash Ghosh的答案提供了該問題的最簡單和 imo 最佳解決方案。

一般來說,避免使用orElse 在這種情況下,將findByIdentificationTypeOrId(String it, String id)添加到您的存儲庫。

@xenteros 是對的,這就是問題所在。 您可以使用findByIdentificationTypeOrId在一個查詢中獲取數據

return specRepo.findByIdentifcationTypeOrId(idType, idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

和存儲庫之類的

@Repository
public interface IdentificationSpecRepository extends CrudRepository<IdentificationMaster, String>{

    Optional<IdentificationMaster> findByIdentificationTypeOrId(String identificationType, String id);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM