简体   繁体   English

限制JPA中集合的大小

[英]Limit the size of a collection in JPA

Say I have an entity like this 说我有这样的实体

@Entity
Class A{
//fields

@Onetomany
Set<B> b; // 
}

Now, how do I limit the number of 'B's in the collection in such a way that, when there is a new entry in the collection, the oldest one is removed, some thing like removeEldestEntry we have in a LinkedHashMap. 现在,我如何限制集合中'B'的数量,使得当集合中有新条目时,最旧的条目被删除,有些像我们在LinkedHashMap中有的removeEldestEntry

I am using MySQL 5.5 DB with Hibernate. 我正在使用带有Hibernate的MySQL 5.5 DB。 Thanks in advance. 提前致谢。

EDIT 编辑

My goal is not to have more than N number of entries in that table at any point of time. 我的目标是在任何时间点都不要在该表中有超过N个条目。 One solution I have is to use a Set and schedule a job to remove the older entries. 我的一个解决方案是使用Set并安排作业来删除旧条目。 But I find it dirty. 但我发现它很脏。 I am looking for a cleaner solution. 我正在寻找一个更清洁的解决方案。

There is one API provided by Apache Commons Collection . Apache Commons Collection提供了一个API。 Here you can use the class CircularFifoBuffer for your reference of the same problem you have, if you want example shown as below that you can achive that 在这里你可以使用CircularFifoBuffer类来引用你遇到的同样问题,如果你想要如下所示的例子你可以实现

Buffer buf = new CircularFifoBuffer(4);
buf.add("A");
buf.add("B");
buf.add("C");
buf.add("D"); //ABCD
buf.add("E"); //BCDE

I would use the code to manually enforce this rule. 我会使用代码手动强制执行此规则。 The main idea is that the collection B should be well encapsulated such that client only can change its content by a public method (ie addB() ) . 主要思想是集合B应该被很好地封装,使得客户端只能通过公共方法(即addB() )来改变其内容。 Simply ensure this rule inside this method ( addB() ) to ensure that the number of entries inside the collection B cannot larger than a value. 只需在此方法( addB() )中确保此规则,以确保集合B内的条目数不能大于值。

A: A:

@Entity
public class A {


    public static int MAX_NUM_B = 4;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<B> b= new LinkedHashSet<B>();

    public void addB(B b) {
        if (this.b.size() == MAX_NUM_B) {
            Iterator<B> it = this.b.iterator();
            it.next();
            it.remove();
        }
        this.b.add(b);
    }

    public Set<B> getB() {
        return Collections.unmodifiableSet(this.b);
    }
}

B: B:

@Entity 
public class B{

    @ManyToOne
    private A a;
}

Main points: 要点:

  • A should be the owner of the relationship. A应该是关系的所有者。
  • In A , do not simply return B as client can bypass the checking logic implemented in addB(B b) and change its content freely.Instead , return an unmodifiable view of B . 在A中,不要简单地返回B,因为客户端可以绕过addB addB(B b)实现的检查逻辑并自由地更改其内容。相反,返回B的不可修改的视图。
  • In @OneToMany , set orphanRemoval to true to tell JPA to remove the B 's DB records after its corresponding instances are removed from the B collection. 在@OneToMany中,将orphanRemoval设置为true以告诉JPA在从B集合中删除相应的实例后删除B的DB记录。

I think you will have to do it manually. 我想你必须手动完成它。

One solution that comes to mind is using @PrePersist and @PreUpdate event listeners in entity A . 想到的一个解决方案是在实体A使用@PrePersist@PreUpdate事件侦听器。

Within the method annotated with above annotations , you check if size of Set<B> , if it is above the max limit, delete the oldest B entries(which may be tracked by a created_time timestamp property of B) 在使用上述注释注释的方法中,检查Set<B>大小,如果它高于最大限制,则删除最旧的B条目(可以通过B的created_time timestamp属性跟踪)

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

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