首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenJPA急切抓取

OpenJPA急切抓取
EN

Stack Overflow用户
提问于 2014-04-03 14:56:08
回答 2查看 1.3K关注 0票数 2

我使用OpenJPA 2.3与WebSphere 8.5捆绑在一起,我必须从一个表中读取大量数据。我还得找出许多与根实体的关系。

Atm我正在使用条件API创建搜索查询并选择实体。我热切地注释了所有的集合。当我检查日志文件时,它会创建5个查询来获取所有的子查询。这就是我想要的方式。问题是,在选择之后,我必须在java中筛选很多,在1000个匹配实体之后停止。因此,我认为只要我有1k的结果,我就可以指定提取大小,并停止从db读取实体。

如果引入FetchBatchSize设置,OpenJPA将为每个实体创建单个查询来加载子实体。(n+1问题)

我还试图在查询中直接使用fetch join语法,但没有成功。那我做错什么了?

我试过:

1)

代码语言:javascript
复制
    query.setHint("openjpa.FetchPlan.FetchBatchSize", 1000);
    query.setHint("openjpa.FetchPlan.ResultSetType", "SCROLL_INSENSITIVE"); 

2)

代码语言:javascript
复制
        OpenJPAQuery<?> kq = OpenJPAPersistence.cast(query);
        JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan();
        fetch.setFetchBatchSize(1000);
        fetch.setResultSetType(ResultSetType.FORWARD_ONLY);
        fetch.setFetchDirection(FetchDirection.FORWARD);
        fetch.setLRSSizeAlgorithm(LRSSizeAlgorithm.UNKNOWN);

实体:

代码语言:javascript
复制
@Entity
@Table(name = "CONTRACT")
public class Contract {

// omitted the other properties. The other relationships are annotated the same way
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "contract")
    private List<Vehicle> vehicles= new ArrayList<Vehicle>();

查询:

代码语言:javascript
复制
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Contract> crit = cb.createQuery(Contract.class);
        crit.distinct(true);
        Root<Contract> r = crit.from(Contract.class);

        // omited the where clause. In worst case I have a full table scan without any where clause. (the reason I need the batch size)

        Fetch<Contract, Vehicle> fetchVehicles = r.fetch("vehicles", JoinType.LEFT); // I tried to work with a fetch join as well

                TypedQuery<Contract> query = em.createQuery(crit);

//      query.setHint("openjpa.FetchPlan.FetchBatchSize", FETCH_SIZE);
//      query.setHint("openjpa.FetchPlan.ResultSetType", "SCROLL_INSENSITIVE"); 

        OpenJPAQuery<?> kq = OpenJPAPersistence.cast(query);
        JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan();
        fetch.setFetchBatchSize(FETCH_SIZE);
        fetch.setResultSetType(ResultSetType.FORWARD_ONLY);
        fetch.setFetchDirection(FetchDirection.FORWARD);
        fetch.setLRSSizeAlgorithm(LRSSizeAlgorithm.UNKNOWN);
        fetch.setEagerFetchMode(FetchMode.PARALLEL);

        List<TPV> queryResult = query.getResultList();

        // here begins the filtering and I stop as soon I have 1000 results

谢谢你的帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-10 08:37:49

在我的场景中,似乎有一些应用程序的Bugs。我找到了一个天平很好的方法。

首先,我只选择I(条件API可以选择skalar值),并在那里应用批处理。因此,由于错误的获取策略,我没有n+1问题了。

在此之后,我使用批量为1000的IN()语句来选择我的实体,而不限制获取批处理大小或最大结果。因此,我没有遇到这个bug,OpenJPA为每个关系生成一个查询。

因此,我有大约6个查询实体及其所有依赖项。

再次感谢你的帮助!

票数 0
EN

Stack Overflow用户

发布于 2014-04-03 15:56:29

看一看如何处理大的结果集,你就会发现,“渴望”与你应该做的恰恰相反。

正如我在注释中指出的那样,EAGER意味着JPA同时加载所有结果,因此不建议使用大型结果集。设置fetchBatchSize会导致JPA延迟加载每一个x(在您的例子中是1000)结果。因此,实际上就像使用@OneToMany(fetch = FetchType.LAZY, ...)一样(也值得一试)。

fetchBatch大小设置为更低的数目(例如50)也会降低内存中保存的对象。

也试着

代码语言:javascript
复制
query.setHint("openjpa.FetchPlan.ResultSetType", "SCROLL_SENSITIVE"); 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22841414

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档