最近做項目遇到這樣一個問題,需求類似下面這樣。這裡有兩張表:
表一(test)
表二(test2)
描述
表一存放的是學生各課程的成績,表二存的是學生的總成績。現在需要將表一中學生各課程的成績匯總,並寫入到表二中。於是我使用了如下語句
sql語句
insert into "test1"("studentId","totalScore") select"studentId",sum("score") as totalScore from"test" groupby "studentId" order by "studentId"
這個時候,問題出來了:
[Err] ORA-01400: cannotinsert NULL into ("GXPT_PJ"."test1"."ID")
提示很清楚,ID列不能為空。可是,我們的項目使用了hibernate,數據庫是通過實體映射出來的,而ID使用的hibernate的UUID,也就是說ID是通過hibernate來維護的,在數據庫中根本無法確定ID,這樣就無法插入數據,那麼該怎麼辦呢?
方案一:oracle主鍵自增長
我們開發使用的是oracle數據庫,大家應該知道,oracle不像sqlserver那樣主鍵可以設置成自增長類型,oracle只有sequence,那麼,就使用sequence來實現主鍵自增長吧。
1、創建sequence
createsequence TEST_SEQUENCE minvalue1 NOMAXvalue startwith 1 incrementby 1 NOCYCLE nocache;
2、創建觸發器
create or replace trigger trg_test1 beforeinsert on "test1" for each row begin selectTEST_SEQUENCE.nextval into :new.id from dual; end;
3、再次執行插入語句。結果如下:
達到我們的要求。
缺點:
我們的數據庫是通過hibernate的實體映射出來的,如果使用這種方式,每次映射好數據庫後,還必須手動添加觸發器。另外,如果要換數據庫,其他數據庫未必支持sequence,這樣功能就無法實現,靈活性不夠。
方案二:犧牲效率,增加系統的靈活性。
將表一中的數據匯總後,返回到程序中,然後再通過hibernate插入到表二。
優缺點:
這種方式使用的數據庫,完全用hibernate就可以,不用額外做工作,靈活性較高。但這種方式需要跟數據庫交互兩次,匯總數據需要傳輸一個來回,效率必然比方案一差。
我的選擇
考慮到這個功能使用的頻率不是很高,適當的犧牲點效率,就使得系統的移植性更強,我選擇方案二。
或許hibernate提供了更好的方案,只是小弟不曉得,如果您正好知道,還請留下您的建議。謝謝!