Limit collection size in JPA

Let's say I have an object like

@Entity Class A{ //fields @Onetomany Set<B> b; // } 

Now, how do I limit the amount of β€œB” in the collection in such a way that when the collection has a new entry, the oldest one is deleted, something like removeEldestEntry we have in LinkedHashMap.

I am using MySQL 5.5 DB with Hibernate. Thanks in advance.

EDIT

My goal is not to have more than N number of entries in this table at any given time. One solution is to use Set and schedule a task to delete old records. But I find it dirty. I am looking for a cleaner solution.

+4
source share
3 answers

I would use code to enforce this rule manually. The basic idea is that assembly B needs to be well encapsulated so that the client can modify its content in a public way (i.e. addB() ). Just make sure this rule is inside this method ( addB() ) so that the number of records inside collection B does not exceed the value.

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); } } 

IN:

 @Entity public class B{ @ManyToOne private A a; } 

Basic moments:

  • A must be the owner of the relationship.
  • In A, it is not easy to return B, since the client can bypass the verification logic implemented in addB(B b) and freely change its contents. Instead, return unmodified view B.
  • In @OneToMany, set orphanRemoval to true to tell JPA to delete B records after the corresponding instances are removed from collection B.
+2
source

There is one API provided by the Apache Commons Collection . Here you can use the CircularFifoBuffer class to help you know about the same problem you have, if you want the example below to show that you can achieve this

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

I think you have to do it manually.

One solution that comes to mind uses @PrePersist and @PreUpdate event listeners in entity A

As part of the method annotated with the above annotations, you check if the size of Set<B> , if it exceeds the maximum limit, delete the oldest entries B (which can be tracked by the created_time value for B)

+1
source

All Articles