【问题标题】:@OneToMany mapping list size limit@OneToMany 映射列表大小限制
【发布时间】:2011-12-15 05:55:56
【问题描述】:

有没有办法限制 JPA 中 @OneToMany 关系的列表大小? 这是我的代码示例:

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST)
private List<Comment> commentList;

我正在使用 EclipseLink 2.3 JPA 实现。 提前致谢。

【问题讨论】:

标签: java jpa one-to-many


【解决方案1】:

Bean Validation Specification (JSR-303) 的一部分是@Size(min=, max=) 注释:

支持的类型有 String、Collection、Map 和数组。检查带注释的元素大小是否介于 min 和 max(含)之间。

您可以验证集合。

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST)
@Size(min=1, max=10)
private List<Comment> commentList;

【讨论】:

    【解决方案2】:

    真正的问题是集合本身。您应该以这种方式为您的业务领域建模。这个解决方案(带有@OneToMany 注释的集合)仅适用于小型集合(数十个对象),而不适用于大型集合(数千个对象),这很可能是 cmets 的情况。你真的必须小心他们,因为他们很快就会失控。我现在使用它们只是为了模拟与Account 关联的Roles 的集合,因为我知道在我的域中没有帐户将拥有超过 9 个角色,并且因为帐户所在的角色是如此对于使用该帐户非常重要。对于所有其他 m 对 n 关系,我使用的是普通的旧查询。

    不要向对象添加 cmets 集合,而是在 Comment 上添加对对象的引用,然后显式使用查询获取所需的 cmets。

    Comment 上定义一个命名查询来获取某个对象的cmets(我们使用Article):

    @Entity
    @NamedQueries(value={
        @NamedQuery(name=Comment.FOR_ARTICLE, query=
            "SELECT c FROM Comment c WHERE c.article = :article"
        )
    })
    public class Comment {
        // ...
        @ManyToOne
        @JoinColumn(name = "articleId")
        private Article article;
    }
    

    然后,使用该命名查询 i.c.w。 Query.setMaxResultsQuery.setFirstResult 明确控制要获得多少结果并允许分页等:

    @PersistenceContext
    EntityManager em;
    
    Article theArticle = ...;
    
    Query query = em.createNamedQuery(Comment.FOR_ARTICLE, Comment.class);
    query.setParameter("article", theArticle);
    query.setFirstResult(0);
    query.setMaxResults(10);
    List<Comment> comments = (List<Comment>) query.getResultList();
    

    要做分页,只需setFirstResult 到对应的第一个结果 要显示的页面。例如。要显示结果 20 .. 29,您会调用 setFirstResult(20).

    【讨论】:

      【解决方案3】:

      您不能在 JPA 中执行此操作,而且它没有意义,因为映射旨在反映关系中有多少对象的现实。

      您这样做是因为性能吗?如果是这样,您可以做的是使用 Lazy 获取样式并使用 Batchsize 注释来指定您想要一次获取多少:

      *更正:@Batchsize 是 Hibernate 功能

      @OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST, fetch=LAZY)
      @BatchSize(size=16)
      private List<Comment> commentList;
      

      然后在您的代码中,只需在此映射集合中迭代/循环到您想要的位置。

      无论哪种方式,根据我的经验,“破解”映射来完成 Criterias/Query 的设计目的并不是一项富有成效的努力,当您需要比 @OneToMany 明确提供的更多控制或性能调整时,最好的方法可能是只是做一个查询。

      【讨论】:

      • 应该澄清你所说的“限制”是什么意思,我的回答涉及模仿 SQL LIMIT。如果您想验证尺寸,请使用 @jeha 回答的尺寸注释。
      • 这是来自 Hibernate 的 Batchsize 吗?
      • 可能,我两个都用,所以我可能把它们弄混了。 :(
      • 因为没有@Batchsize 供我使用:(
      • 我建议只对这样的情况使用查询。我曾经尝试使用“酷”的 ORM 来做所有事情,但是随着我们的应用程序的增长,我们发现大多数映射的集合都被替换为良好的旧查询或 Criterias,以便为我们提供更多的控制和性能。
      【解决方案4】:

      没有真正的正统方式来做到这一点。 我会让关系变得懒惰,查询父对象。之后病房不初始化惰性列表,并基于第一个查询运行另一个查询,该查询在子表上运行。这样,您可以将结果集限制在主要标准上,而不是连接标准上。或者您可以只运行第二个查询(仅在子表上),支持分页。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-16
        • 2013-02-25
        • 1970-01-01
        • 1970-01-01
        • 2020-07-01
        • 2011-06-25
        • 2014-11-19
        相关资源
        最近更新 更多