2017-06-17 40 views
4

我有這樣的需求。Java Hibernate有關更新所有表字段的提示性能

protected Integer[] updateFullTable(final Class clazz){ 
    final ProjectionList projectionList=Projections.projectionList().add(Projections.property("id"),"id"); 
    final Criteria criteria=session.createCriteria(clazz) 
    .add(Restrictions.eq("typeOfOperation",1)) 
    .add(Restrictions.eq("performUpdate",true)); 
    criteria.setProjection(projectionList); 
    final List idsList=criteria.list(); 
    final Integer[]ids = transformObjectArrayIntoIntegerArray(idList); 
    //NOW WE UPDATE THE ROWS IDS. 
    final Query query=session.createQuery("update "+clazz.getName()+" set activeRegister=true and updateTime=:updateTime where id in (:ids)") 
    .setParameter("updateTime",new Date()) 
    .setParameterList("ids",ids); 
    query.executeUpdate();   
    return transform; 
} 

正如你們可以看到我需要更新表中的所有行有時我查詢所有行的id和後來的更新應用到這些ID在一個單獨的查詢,但該表有很多記錄有時需要30秒到10分鐘,取決於表

我已將此代碼更改爲只有一個這樣的更新。

final Query query=session.createQuery("update "+clazz.getName()+" set activeRegister=true and updateTime=:updateTime where typeOfOperation=1 and performUpdate=true"); 

而且與僅查詢我避免先查詢,但我不能不再返回受影響的標識。但後來要求變更爲

final StringBuilder logRevert; 

參數已添加。

如果需要,哪些需要存儲更新的id以將直接反向更新應用到數據庫中。

但隨着我的更新,我無法再讓Ids不再。我的問題是,如何使用存儲過程或數據庫中的某種解決方法獲取或返回受影響的ID或休眠我的意思是僅使用一個查詢或增強代碼獲得第一個行爲。

任何提示。

我已經試過

  1. 使用標準
  2. 使用HQL。
  3. 使用namedQuery
  4. 使用SqlQuery類
  5. 不使用變壓器回到我原始的對象[]

但仍然多次在某種程度上高。

我想是這樣

query.executeUpdate(); // RETURNS THE COUNT OF THE AFFECTED ROWS 

但我需要在受影響的ID ......

很抱歉,如果這個問題很簡單。

UPDATE

隨着@德米特里 - senkovich我能做到這一點使用rawSQL但不是冬眠分離問題在這裏提出。

https://stackoverflow.com/questions/44641851/java-hibernate-org-hibernate-exception-sqlgrammarexception-could-not-extract-re 
+0

如果要減少資源的使用,最大限度提高性能,你必須使用遊標或存儲過程(使用光標)如果你不關心浪費了一些週期,你的時鐘是可靠的,你也可以改變你的算法首先進行更新。更新後,您可以通過使用時間戳,您爲行設置,在我需要獲取ID並在以後更新這些ID在哪裏條款 –

回答

4

怎麼樣以下解決方案?

SET @ids = NULL; 

UPDATE SOME_TABLE 
SET activeRegister = true, updateTime = :updateTime 
WHERE typeOfOperation = 1 and performUpdate = true 
     AND (SELECT @ids := CONCAT_WS(',', id, @ids)); 

SELECT @ids; 
+0

我怎樣才能返回這些ids使用休眠使用sqlQuery左右? – chiperortiz

+0

@chiperortiz我看到最簡單的方法是使用本地查詢:執行Session.createSQLQuery(this_long_query_above) –

+0

但我得到的ID?我會看看。 – chiperortiz

1

如果錄入爲datetime 您可以選擇與所有受影響的記錄ID選擇

Date updateTime = new Date(); // time from update

select id from clazz.getName() where updateTime=:updateTime and activeRegister=true and typeOfOperation=1 and performUpdate=true 
+0

獲得ids。我只需要使用1個sql語句或儘可能快...... – chiperortiz

+0

@chiperortiz - 「儘可能快」 - 不必擔心優化,直到您證明它是最慢的部分碼。 –

1

更新表中的大量行是一個緩慢的操作。這是由於需要捕捉每行的「老字號」的值在ROLLBACK的情況下(由於明確ROLLBACKUPDATE,故障或在同一交易後續查詢,或電源故障的故障前UPDATE結束)。

通常的修復方法是重新考慮應用程序設計,這需要較大的UPDATE

在那裏另一方面,有可能修復到架構。請提供SHOW CREATE TABLE所以我沒有做盡可能多的「揮手」下段...

可能是更好的移動需要被更新到一個單獨的列(S)並行,表格(「垂直分區」)。這可能是有益的,如果

  • 原來的表有大量的列寬(TEXTBLOB等) - 由於不必使大副本。
  • 原始表正被同時更新, - 通過不相互阻塞的更新。
  • SELECT打非更新的列 - 通過避免某些其他的阻塞。

你仍然可以得到原始的一組列 - 通過JOINing這兩個表在一起。