一個神奇的錯誤

本週遇到了一個很神奇的錯誤, 項目中有兩個表試卷(Paper), 試卷部分(Part),
他們是一對多關係, 一直以來, 經過jpa的findById總能得的我想要的結果,但此次, 在paper和part的關聯關係都正常的狀況下,居然查詢不出來, 仍是讓本身感受很神奇的。git

尋找問題

開始的時候,大概瀏覽了一下代碼, 沒看到有什麼問題,既然是查詢沒出結果,那就看看生成的sql語句吧,
application.ymlgithub

....
spring:
  jpa:
    hibernate:
        # 顯示sql
       show-sql: ${show-sql:true}
    properties:
      hibernate:
       # 格式化sql
        format_sql: true
  ....

經過findById查詢試卷時生成的sql以下spring

Hibernate: 
    select
        paper0_.id as id1_11_,
        ......
    from
        paper paper0_ 
    where
        paper0_.id=? 
        and paper0_.deleted=0
....
Hibernate: 
    select
        parts0_.paper_id as paper_id5_13_0_,
        ......
    from
        part parts0_ 
    inner join
        course course1_ 
            on parts0_.course_id=course1_.id 
            ......
    where
        parts0_.paper_id=?
        ......

課程(Course)和試卷部分(Part)居然是經過內連接(inner join)鏈接的sql

inner join

image.png

在inner join的狀況下, 必須雙方都有該數據才行, 也就是說, 在上例中, part必須和course有關聯數據纔可以被查詢出來, 是這個緣由?
來到數據庫中一看, 確實part對couse的外鍵是空的。數據庫

這裏只是簡單的介紹一下inner join, 如果對這方面不瞭解,能夠看學長的這篇文章segmentfault

爲何會是內連接

關於爲何會是內連接, 咱們來到Part實體定義的文件,會發現有這麼一個約束
image.png架構

@JoinColumn(nullable = false)

該註解定義了, 該外鍵不會爲null,因此使用inner join, 同時,由於這個字段是經過flyway在後期加入的,但並無在數據庫的結構中定義not null, 兩方面形成了此次的能夠插入但不能查詢的問題app

@NotNull vs @Column(nullable = false)

發現網上有把這兩個做對比的,就看了看, @Column(nullable = false)和@JoinColumn(nullable = false)我感受時同樣的,只是一個做用於普通的字段(Long ,String ......),一個做用於有外鍵關係的對象,因此只談其中一個。spa

@NotNull是JSR 303 Bean驗證批註。它與數據庫約束自己無關。因爲Hibernate是JSR 303的參考實現,所以它會智能地選擇這些約束並將它們轉換爲數據庫約束,所以你至關於得到了兩個約束條件。@Column(nullable = false)是JPA聲明列爲非空的方法。即,前者用於驗證,然後者則用於指示數據庫架構詳細信息。
JSR是Java Specification Requests的縮寫,意思是Java 規範提案。是指向 JCP(Java Community Process)提出新增一個標準化技術規範的正式請求。任何人均可以提交JSR,以向Java平臺增添新的API和服務。JSR已成爲Java界的一個重要標準。

拿上面使用的 @JoinColumn(nullable = false)的例子舉例, 若咱們在這裏使用的@NotNull,那麼咱們雖然數據庫中沒有約束,仍然沒法保存成功,會提示
image.pnghibernate

因此, 當咱們僅僅須要驗證的時候,@NotNull是一個比 @Column(nullable = false), 更好的選擇,此外,如果想要在使用@NotNull時可以讓Hibernate把咱們生成數據庫的約束,咱們須要確保 **hibernate.validator.apply_to_ddl_=true(默認即爲true)**

版權聲明

本文做者: 河北工業大學夢雲智開發團隊 - 李宜衡

參考文章

Confusion: @NotNull vs. @Column(nullable = false) with JPA and Hibernate
Hibernate @NotNull vs @Column(nullable = false)
JSR-303

相關文章
相關標籤/搜索