1. 程式人生 > >spring data jpa遇到的一些瑣碎問題

spring data jpa遇到的一些瑣碎問題

jpa是幾年前就已經接觸過了,不過中間隔了好久沒使用過,忘了不少細節上的問題。今天就來分享下在專案中遇到的一些坑吧,應該都比較基礎,注意就好。
1.物件與表的對映。
全程採用註解形式,物件中的欄位可以根據資料表的欄位進行定義,但是在建資料表的時候要保證資料表字段都要是大寫,否則在關聯關係(如:一對多,多對一,多對多等)上一直會出錯,說找不到對應的列。對於物件的get、set方法,可以直接採用簡便的@Data在類上進行標註即可,然後在屬性上新增欄位的對映註解。


2.物件的構造方法的注入
很多時候,我們會根據業務來寫HQL,但是HQL自身的功能有限不能完全滿足業務,我們會根據需要來查詢物件,有的時候要查詢一張資料表中不存在的欄位,這時候要在物件中新增需要的屬性,並且要給該屬性新增@Transient註解,同時給該物件新增一個構造方法public User(Long id,String deptName) { this...省略},顯然預設的構造方法一定要加上public User() { },這樣就可以實現多個物件的關係關聯,查詢的時候就可以這樣select new User(u.id,d.deptName) from User u,Dept d where u.deptId = d.id;


3.聚合函式在構造器中的注入

在業務統計的時候,會涉及到一些資料的統計。這時候資料庫的sum,count,avg等函式就要被派上用場,但在物件模型中,並不完全跟資料庫寫法一樣。首先,在物件中定義sum的屬性要是Long型的,count的可以是Long,也可是Integer,同時要給該屬性加上@Transient註解,因為它在資料表中不存在,只是一個臨時變數,建立構造器public Course(Long userId,Integer level,Long total){this...省略}。其次,在查詢語句中我們會根據不同條件或維度來統計結果,如select  new Course(u.userId,case when u.level is null then  0 else u.level,sum(case when c.score>=90 then 1 when c.score <90 and c.score>=80 then 1 when c.score <80 and c.score>=60 then 1 when c.score<60 then 1 else 0 end )) from Course c,User u where c.UserId=u.id group by u.userId,case when u.level is null then  0 else u.level;問題有兩個:1、為什麼給level加case when判斷呢,因為有時候會產生髒資料,一旦資料為空,查詢的時候會報javax.servlet.ServletException: null ,這個問題還真不好找;2、為什麼在sum裡面使用case when,那是因為hql不支援decode這個函式,所以要使用該函式。


4.使用EntityManager執行原生sql
有的時候,業務很複雜的情況下,我們還是要採用原生sql完成該業務,首先新增這個兩個註解@Transactional @Service在類上,然後在把@PersistenceContext private EntityManager em;寫入該類全域性屬性,如果是查詢的話,這個比較容易,直接寫sql,建立Query,然後查出結果集;如果是增刪改,需要在相應的類上加上@Modifying註解,
如@Modifying public void batchInsert(){}。有@Transactional的情況下,事務是滿足原子性、一致性、隔離性、永續性的特點,如果哪裡出錯,會同時提交或回滾。可以藉助於try{}catch(){}來實現不同時進行,具體可以自行嘗試,這裡就不多說了。