本週遇到了一個很神奇的錯誤, 項目中有兩個表試卷(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的狀況下, 必須雙方都有該數據才行, 也就是說, 在上例中, part必須和course有關聯數據纔可以被查詢出來, 是這個緣由?
來到數據庫中一看, 確實part對couse的外鍵是空的。數據庫
這裏只是簡單的介紹一下inner join, 如果對這方面不瞭解,能夠看學長的這篇文章segmentfault
關於爲何會是內連接, 咱們來到Part實體定義的文件,會發現有這麼一個約束架構
@JoinColumn(nullable = false)
該註解定義了, 該外鍵不會爲null,因此使用inner join
, 同時,由於這個字段是經過flyway
在後期加入的,但並無在數據庫的結構中定義not null
, 兩方面形成了此次的能夠插入但不能查詢的問題app
發現網上有把這兩個做對比的,就看了看, @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,那麼咱們雖然數據庫中沒有約束,仍然沒法保存成功,會提示hibernate
因此, 當咱們僅僅須要驗證的時候,@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