谨慎使用Hibernate中的本机SQL
我真的很喜歡Hibernate,但我也不知道同時具備強大功能和欺騙性的工具。 我可以寫一本書,講述僅與Hibernate相關的生產和貨物崇拜編程中的意外情況。 與用戶相比,與工具相比,這更多的是問題,但請不要讓它過于保修。
所以,這是一個最近的例子。
問題
我們需要一個后臺作業,該作業列出目錄中的所有文件,并將每個文件的條目插入表中。
天真的解決方案
該作業以前是用Bash編寫的,并且可以從表中直接讀取SQL。 所以,盲人,讓我們寫一些直接的SQL!
for (String fileName : folder.list()) {SQLQuery sql = session.getDelegate().createSQLQuery("insert into dir_contents values (?)");sql.setString(0, fileName);sql.executeUpdate(); }它行得通嗎? 當然可以。
現在,如果文件夾中有10,000個文件怎么辦? 如果您還有一個不太優雅的域模型 ,在一個上下文中有太多的實體類,數千個實例和兩級緩存,該怎么辦?
突然,這項瑣碎的工作需要10分鐘才能執行,所有時間使2或3個CPU保持100%繁忙。
什么,只要一堆插入物?
簡易修復
問題在于它是休眠狀態。 它不僅是一個愚蠢的JDBC包裝器,而且還有很多事情要做。 它試圖使緩存和會話狀態保持最新。 如果運行裸露的SQL更新,則不知道要更新的表,它所依賴的表以及它如何影響一切,以防萬一它幾乎刷新了所有內容 。
如果您在如此擁擠的環境中執行此操作10,000次,則總和會增加。
這是修復它的一種方法-而不是使用刷新運行10,000個更新,而是在一個塊中執行所有操作并刷新一次。
session.doWork(new Work() {public void execute(Connection connection) throws SQLException {PreparedStatement ps = connection.prepareStatement("insert into dir_contents values (?)");for (String fileName : folder.list()) {ps.setString(1, fileName);ps.executeUpdate();}} });其他解決方案
驚喜,驚喜:
- 一定要使用休眠模式。 創建一個代表DirContents的真實實體,并像其他所有東西一樣使用它。 然后,Hibernate知道何時刷新哪些緩存,如何批處理更新等等。
- 不要使用休眠模式。 使用普通的舊JDBC, MyBatis或其他適合您的堆棧或已經存在的堆棧。
帶走
即使此示例不是最佳用例,本機SQL也應有的地位。 無論如何,關鍵是:如果將本地SQL與Hibernate一起使用,請注意會話狀態和緩存。
翻譯自: https://www.javacodegeeks.com/2014/03/careful-with-native-sql-in-hibernate.html
總結
以上是生活随笔為你收集整理的谨慎使用Hibernate中的本机SQL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux查找命令find(linux
- 下一篇: 华为DDOS(华为DDOS分析报告)