Spring Data JPA 中的 NonUniqueResultException
一、簡介
Spring Data JPA 提供了一個簡單且一致的接口,用於訪問存儲在各種關係數據庫中的數據,使開發人員更容易編寫與數據庫無關的代碼。它還消除了對大量樣板代碼的需求,使開發人員能夠專注於構建其應用程序的業務邏輯。
但是,我們仍然需要確保正確的返回類型,否則會拋出Exception 。在本教程中,我們將重點關注NonUniqueResultException
。我們將了解導致它的原因以及遇到它時如何修復我們的代碼。
2. NonUniqueResultException
當預期查詢方法返回單個結果但發現多個結果時,Spring Data JPA 框架會拋出NonUniqueResultException
運行時異常。當使用 Spring Data JPA 的查詢方法之一(例如findById()
、 findOne()
或不返回 collection 的自定義方法執行查詢時,可能會發生這種情況。
當拋出NonUniqueResultException
時,這意味著正在使用的方法旨在返回單個結果,但它發現了多個結果。這可能是由於查詢不正確或數據庫中的數據不一致。
3.例子
讓我們使用我們從文章 Query Entities by Dates and Times with Spring Data JPA 中了解到的Entity
:
@Entity
public class Article {
@Id
@GeneratedValue
private Integer id;
@Temporal(TemporalType.DATE)
private Date publicationDate;
@Temporal(TemporalType.TIME)
private Date publicationTime;
@Temporal(TemporalType.TIMESTAMP)
private Date creationDateTime;
}
}
現在,讓我們創建我們的ArticleRepository
並添加兩個方法:
public interface ArticleRepository extends JpaRepository<Article, Integer> {
List<Article> findAllByPublicationTimeBetween(Date publicationTimeStart, Date publicationTimeEnd);
Article findByPublicationTimeBetween(Date publicationTimeStart, Date publicationTimeEnd);
}
這兩種方法之間的唯一區別是findAllByPublicationTimeBetween()
具有List
< Article>
作為返回類型,而findByPublicationTimeBetween()
具有單個Article
作為返回類型。
當我們執行第一個方法findAllByPublicationTimeBetween
時,我們總是會得到一個集合。根據我們數據庫中的數據,我們可以獲得一個空List
或一個包含一個或多個Article
實例的List
。
第二種方法findByPublicationTimeBetween
在技術上也可以工作,因為數據庫恰好包含零個或一個匹配的Article
。如果給定查詢沒有單個條目,該方法將返回null
。另一方面,如果有一個對應的Article
,它將返回單個Article
。
但是,如果有多個Article
與findByPublicationTimeBetween
的查詢相匹配,該方法將拋出NonUniqueResultException
,然後將其包裝在IncorrectResultSizeDataAccessException
中。
當這樣的異常在運行時隨機發生時,表明數據庫設計或我們的方法實現有問題。在下一節中,我們將了解如何避免此錯誤。
4. 避免NonUniqueResultException
的技巧
為避免NonUniqueResultException
,仔細設計數據庫查詢並正確使用 Spring Data JPA 的查詢方法非常重要。在設計查詢時,確保它始終返回預期數量的結果非常重要。我們可以通過仔細指定我們的查詢條件來實現這一點,例如使用唯一鍵或其他識別信息。
在設計查詢方法時,我們應該遵循一些基本規則來避免NonUniqueResultExceptions
:
- 如果可能返回多個值,我們應該使用**
List
或Set
**作為返回類型。 - 如果我們可以通過數據庫設計確保只有一個返回值,我們就只使用一個單一的返回值。當我們尋找唯一鍵(如
Id
、UUID
)時,情況總是如此,或者根據數據庫設計,它也可能是保證唯一的電子郵件或電話號碼。 - 確保只有一個返回值的另一種方法是將返回限制為單個元素。這可能很有用,例如,如果我們總是想要最新的
Article
。
5.結論
NonUniqueResultException
是使用 Spring Data JPA 時需要理解和避免的重要異常。它發生在查詢預期返回單個結果但找到多個結果時。我們可以通過確保我們的JpaRepository
方法返回正確數量的元素並相應地指定正確的返回類型來防止這種情況。
通過理解並正確避免NonUniqueResultException
,我們可以確保我們的應用程序能夠一致且可靠地訪問數據庫中的數據。
與往常一樣,這些示例也可以在 GitHub 上找到。