Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Eclipselink:批读取会创建大量查询_Java_Sql_Jpa_Eclipselink - Fatal编程技术网

Java Eclipselink:批读取会创建大量查询

Java Eclipselink:批读取会创建大量查询,java,sql,jpa,eclipselink,Java,Sql,Jpa,Eclipselink,我使用eclipselink 2.6.4,我有以下实体 @Entity @Table(name = "articles") public class Article { @Id @Column(name = "id") private Integer id; @Column(name = "title") private String title; @OneToMany(fetch = FetchType.EAGER,mappedBy = "

我使用eclipselink 2.6.4,我有以下实体

@Entity
@Table(name = "articles")
public class Article {

    @Id
    @Column(name = "id")
    private Integer id;

    @Column(name = "title")
    private String title;

    @OneToMany(fetch = FetchType.EAGER,mappedBy = "article")
    @BatchFetch(BatchFetchType.IN)
    private List<Author> authors

    //+ setters and getters
}

@Entity
@Table(name = "authors")
public class Author {

    @Id
    @Column(name = "id")
    private Integer id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "articleId")
    private Article article;

    @Column(name = "surname")
    private String surname;

    //+setters and getters
}
为什么有这么多疑问?我预计只有两个问题。我犯了什么错

编辑
我又做了两次测试:

  • 我只在字段作者的文章类中使用了注释
    @BatchFetch(BatchFetchType.IN)
    (没有向查询添加提示)
  • 我没有使用注释
    @BatchFetch(BatchFetchType.IN)
    ,但在查询时使用了两个提示:

    String queryString=“从文章e中选择e”; Query Query=em.createQuery(queryString); setHint(“eclipseelink.batch.type”,“IN”); setHint(“eclipselink.batch”、“e.authors”); query.setFirstResult(0); query.setMaxResults(10); List items=query.getResultList()

  • 表中的数据包括:

    | id | title    |
    -----------------
    | 1  | article1 |
    | 2  | article2 |
    | 3  | article3 |
    
    表中的数据作者:

    | id | articleId |  surname  |
    ------------------------------
    | 1  |  1        |  Author1  |
    | 2  |  1        |  Author2  |
    | 3  |  2        |  Author3  |
    | 4  |  2        |  Author4  |
    | 5  |  3        |  Author5  |
    | 6  |  3        |  Author6  |
    
    在每个测试中,执行6个查询:

    SELECT id AS a1, title AS a2 FROM articles LIMIT ? OFFSET ? bind => [2 parameters bound]
    SELECT id, surname, articleId FROM authors WHERE (articleId IN (?,?,?)) bind => [3 parameters bound]
    SELECT id, title FROM articles WHERE (id = ?) bind => [1 parameter bound]
    SELECT id, surname, articleId FROM authors WHERE (articleId = ?) bind => [1 parameter bound]
    SELECT id, title FROM articles WHERE (id = ?) bind => [1 parameter bound]
    SELECT id, surname, articleId FROM authors WHERE (articleId = ?) bind => [1 parameter bound]
    

    根据以下文件:

    因此,我猜会生成多个选择,因为缓存中没有对象。您尝试的是使用热缓存运行相同的查询


    此外,根据您的要求,您也可以查看这一点。

    有两种方法可以设置批取

  • 注释上方
    @BatchFetch(BatchFetchType.IN)
  • 超过查询提示
    query.setHint(QueryHints.BATCH,column)
    query.setHint(QueryHints.BATCH\u类型,BatchFetchType.IN)
  • 在您的例子中,我看到您在
    作者
    表中添加了注释,但在
    文章
    表中完成了带提示的查询。我不知道这背后的全部逻辑,但我建议:

    @Entity
    @Table(name = "articles")
    public class Article {
    
        @Id
        @Column(name = "id")
        private Integer id;
    
        @Column(name = "title")
        private String title;
    
        @OneToMany(mappedBy = "article", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        @BatchFetch(BatchFetchType.IN)
        private List<Author> authors
    
        //+ setters and getters
    } 
    
    @Entity
    @Table(name = "authors")
    public class Author {
    
        @Id
        @Column(name = "id")
        private Integer id;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "articleId")
        private Article article;
    
        @Column(name = "surname")
        private String surname;
    
        //+setters and getters
    }
    
    Eclipse链接使用相同的:

    OneToMany: LAZY
    ManyToOne: EAGER
    ManyToMany: LAZY
    OneToOne: EAGER
    

    @OneToMany必须是(fetch=FetchType.EAGER),而@ManyTone必须是(fetch=FetchType.LAZY)

    前两个查询是基于JPQL和1:M上的batchFetch的,与预期的一样。第三个查询来自@batchFetch注释,看起来是正确的,虽然我不太明白为什么在本质上是OneToOne的东西上使用batchfetch而不是使用@JoinFetch这样的东西:我看不出在两个查询中这样做有什么好处

    这看起来像EclipseLink中的一个bug,当在循环关系中涉及的一个急切的OneToOne类型映射上使用BatchFetch时-BatchFetch仅用于对集合类型的查询,并且可能会强制读取数据库而不是使用缓存。 选项包括:

  • 将一侧设置为惰性,以便所有项目实例都将完全处于活动状态
    EclipseLink需要构建Author.article之前的内置内存 关系
  • 删除上的@BatchFetch(BatchFetchType.IN) 多人关系。使用@FetchJoin或查询提示 在其他查询中需要时指定BatchFetch:两个选项都不可用 此查询需要

  • 没有逻辑,因为在第二次查询之后,这些对象已经在cache.Hi中。由于分页,我使用批处理。查看我的问题和您的答案。我的答案是不要对集合使用获取联接。连接对于OneToOne和ManyToOne关系来说很好,因为它们不会更改返回的行数。批量抓取在1:1的情况下可能很有用,但可能不是您在这里的最佳选择。此外,无论如何,如果有两个选项-联合抓取和批量,我希望能够同时使用这两个选项。您误读了我的答案,因为我建议您在接受的答案中制定的解决方案。这个问题是由于循环关系和你渴望获取一切;您的设置使EL开始构建文章,从A1开始,然后是所有作者(B1、B2..)。在构建B2的过程中,需要构建尚未构建的A2,强制查询。将其中一个关系切换为惰性将解决此问题,因为当需要时,所有对象都将在缓存中-这就是您使用的方法。另一个选项是在1:1关系上使用fetch join。这也会起作用,但会迫使查询中不必要的表联接引入作者。这将导致建立作者,当它需要构建尚未构建的文章时,信息将包含在行中,因此不需要额外的查询。如前所述,这些数据已经存在,只是1:1的批处理机制没有寻找它,应该作为一个bug进行归档。有关
    @BatchFetch vs@JoinFetch
    和查询优化的更多信息,我尝试了两个测试:1)我对作者2只使用了注释
    @BatchFetch(BatchFetchType.IN)
    。结果相同-6个查询。请用最新的更改和结果更新您的问题。现在很难说是怎么回事了。FetchType。
    EAGER
    你能删除或改成
    LAZY
    LAZY
    =需要时取
    EAGER
    =立即取)问题解决了
    @OneToMany
    必须是
    (fetch=FetchType.EAGER)
    @ManyToOne
    必须是
    (fetch=FetchType.LAZY)
    。在本例中,我只有两个查询,尽管Author类中的article不是null。把它作为答案,我会接受你给我的暗示。
    When using BatchFetchType=IN, EclipseLink selects only objects not already in the cache. This method may work better with cursors or pagination, or in situations in which you cannot use a JOIN. On some databases, this may only work for singleton IDs.
    
    @Entity
    @Table(name = "articles")
    public class Article {
    
        @Id
        @Column(name = "id")
        private Integer id;
    
        @Column(name = "title")
        private String title;
    
        @OneToMany(mappedBy = "article", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        @BatchFetch(BatchFetchType.IN)
        private List<Author> authors
    
        //+ setters and getters
    } 
    
    @Entity
    @Table(name = "authors")
    public class Author {
    
        @Id
        @Column(name = "id")
        private Integer id;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "articleId")
        private Article article;
    
        @Column(name = "surname")
        private String surname;
    
        //+setters and getters
    }
    
    String queryString="SELECT e FROM Article e";
    Query query = em.createQuery(queryString);
    query.setHint("eclipselink.batch.type", "IN");
    query.setHint("eclipselink.batch", "e.authors");
    query.setFirstResult(position);
    query.setMaxResults(amount);
    List<Article> items=query.getResultList();
    
    OneToMany: LAZY
    ManyToOne: EAGER
    ManyToMany: LAZY
    OneToOne: EAGER
    
    OneToMany: LAZY
    ManyToOne: EAGER
    ManyToMany: LAZY
    OneToOne: EAGER