2014-01-15 71 views
0

對於Hibernate的3.5.4,讓我們說我有這樣的定義休眠實體:可以在第二級緩存中Hibernate批量查詢收集遺漏嗎?

@Entity 
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
public class Team { 

    @Id 
    protected Long id; 
    protected List<Player> players; 

    @OneToMany(targetEntity = Player.class, fetch = FetchType.LAZY) 
    @JoinColumn(name = "team_id") 
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
    @NotFound(action= NotFoundAction.IGNORE) 
    @org.hibernate.annotations.BatchSize(size = 50) 
    public List<Player> getPlayers() { 
     return this.players; 
    } 

    pubic List<Player> setPlayers(List<Player> players) { 
     this.players = players; 
    } 

    // More stuff 

} 

然後,我有一個Player實體定義爲你所期望的那樣。從邏輯上講,這將創建三個二級高速緩存對象:

  • Team.players
  • 球員

我發現,如果Team.players緩存被禁用或空的被查詢的團隊,Hibernate會向數據庫發出一個批量請求,在這個請求中它爲一個團隊用一個查詢檢索所有玩家(查找player.team_id = Team.Id)。但是,如果Team.players緩存包含Team和玩家列表之間的緩存關聯,並且這些Player對象在Player緩存中不存在,那麼Hibernate將通過Player.Id一次檢索一個Player Player對象之一分開數據庫查詢。 有什麼辦法讓Hibernate在批處理中檢索這些集合字段對象緩存未命中?

我試過以下參數的設定值,但他們似乎並不影響這種行爲:

  • default_batch_fetch_size
  • jdbc.batch_versioned_data
  • jdbc.batch_size
  • JDBC .fetch_size

我也試過EAGER取代LAZY。

這個冬眠論壇帖子從2008年暗示到這個問題(https://forum.hibernate.org/viewtopic.php?t=983649),但我還沒有出現任何解決方案。謝謝您的幫助!

回答

0

是的,你可以做到這一點。

建立一個Collection<Long>(假設這是你的播放器ID類型)。遍歷團隊的玩家列表,使用Hibernate.isInitialized(player)檢查玩家對象。如果它爲假,請將該ID添加到集合中。這是假設你的@Id在他們的球員的身份證獲得者(而不是領域),所以你可以從球員代理得到身份證,而無需去DB。

如果您使用的是Java EE 6:而不是Hibernate.isInitialized(player),請嘗試em.getEntityManagerFactory().getPersistenceUnitUtil().isLoaded(player)。這對於容器獨立性是首選。

當你有清單檢查它是否是空的。如果不是空的,運行一個查詢:

SELECT p 
JOIN Player p 
WHERE p.id IN (:idList) 

設置idList參數與Collection<Long>

只要運行query.getResultList();不要打擾在任何地方存儲查詢結果。這將實現以前從團隊集合中加載的代理。

+0

嗯,這是有道理的,但我很希望有一個註解或配置參數的解決方案,而不是必須修改我的代碼庫中我偶然使用集合的各個地方......或者甚至可以這樣做被直接烘烤到收集的收集將是很好的。任何想法,如果這是可能的?謝謝您的幫助! – Mike

+0

我想不出任何註解來解決這個問題,但我對Hiberate專有的知識並不是很熟悉。這是解決二級「啄木鳥」問題時唯一可以找到的解決方案。就個人而言,我只將第二級緩存應用於我願意將每個緩存中的每個緩存......實體的安全訪問實體。如果您滿足於存儲您擁有的每個玩家(並且將擁有),我會將您的緩存設置得足夠大並且永不過期,問題就會消失。 –

相關問題