繁体   English   中英

如何在休眠状态下处理大型集合

[英]How to handle large collections in hibernate

我有一个Entry实体和一个Comment实体。 Entry实体与Comment实体具有OneToMany关联:

@Entity
@Table(name="entries")
public class Entry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @OneToMany(mappedBy = "entry", cascade = CascadeType.ALL, orphanRemoval = true)
    @LazyCollection(LazyCollectionOption.EXTRA)
    private List<Comment> comments = new ArrayList<>();

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public List<Comment> getComments() {
        return comments;
    }

    public boolean containsComment(int commentId) {
        return comments.contains(commentId);
    }

    public Comment getComment(int commentId) {
        return comments.get(commentId);
    }

    public void removeComment(Comment comment) {
       comments.remove(comment);
    }
}


@Entity
@Table(name="comments")
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public int id;

    @ManyToOne
    private Entry entry;

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Entry getEntry() {
        return entry;
    }

    public void setEntry(Entry entry) {
        this.entry = entry;
    }
}

假设我有一个单页应用程序,它将以下请求发送到后端:

/deleteComment?entryId=5&commentId=7

我的方法是在控制器中通过entryId参数获取Entry。 比我想在Entry-entity上调用containsComment)()方法,我将在其中传递commentId请求参数。 因此,如果集合包含具有给定id或false的注释,我将为true。 如果为true,则将调用getComment()方法来获取Comment实体。 最后,我将简单地使用Comment实体作为参数调用removeComment()方法。

在PHP Doctrine中,我认为这种方法有效。 这也是休眠的正确方法吗?

在示例代码中,如果我调用containsComment()方法,则会收到以下异常:

org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [public int com.mypackage.Comment.id] by reflection for persistent property [com.mypackage.Comment#id] : 7

请注意,我使用EXTRA-LAZY是因为注释可以快速收集大量内容。

您可以通过查询来做到这一点,例如,如果Comment具有对Entry的引用,请使用select c from Comment c where c.id = :commentId and c.entry.id = :entryId如果您获得该注释,则该注释存在您可以立即使用它。

删除评论很容易,只需执行即可。 由于Comment是关系删除的所有者,因此它也会有效地将其从条目中删除。

忠告一词:HQL / JPQL查询使用关键字id作为id属性。 在您的情况下,因为id@Id注释是可以的。 但是,如果您还有另一个@Id字段,则查询的行为将与您期望的不同,因为在查询中使用id将假设您的意思是@Id字段。

最后,在comments.contains(commentId)上做一个comments.contains(commentId) :像列表这样的Java集合通常会寻找您作为参数传递的元素,但是由于您的集合是List<Comment>并且您传递了一个id(它是一个int ),因此不应被发现。 我不确定Hibernate集合是否采用了某些特殊的翻译逻辑,但是对于Java程序员来说,调用看起来像是一个错误,因为您从不希望它返回true(就像“苹果列表中是否包含这种橙色?”) 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM