Announcement Announcement Module
No announcement yet.
how to avoid dbref loops? Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • how to avoid dbref loops?

    hi i'm new to spring data and i'm considering using it in one of my projects and doing some tests..

    i have the class Person with a @DBRef to another Person object,so i can have like 3 person with a circular reference
    like this:


    now if i get the first person from the database i fall in a loop because mongo keeps trying to fetch the person inside a person so -> stack overflow

    how can i avoid it?
    i'd like to stop the dbref fetching after the 1st fetch so if i get Person1 i end up having Person1->Person2 where person2 has no(or null,or empty)person field..
    what do i do?is it even possible?

  • #2
    Using AbstractMongoEventListener to prevent DBRef loops

    We ran into the same problem recently. It was pretty clear from the stack trace that we had a DBRef loop and I assumed it was a bug in Spring Data MongoDB. Perhaps the circular dependency could be detected on read. However, I think the better question is how to avoid having it happen in the first place. To do so, you could add an extension of AbstractMongoEventListener to your application and override onBeforeSave() throwing an exception if you detect a circular reference to prevent the problematic object from being persisted.

    public void onBeforeSave(E source, DBObject dbo)
    For example, if you have a category hierarchy and you want to make sure a relationship such as A -> B -> A cannot occur, you could implement your listener as:

    public class CategoryMongoEventListener extends AbstractMongoEventListener<Category> {
    	public void onBeforeSave(final Category source, final DBObject dbo) {
    		if (source.getId() != null && source.getParent() != null) {
    			if (source.getId().equals(source.getParent().getParent().getId())) {
    				throw new IllegalArgumentException("Cyclical category reference detected!");
    You would probably want to recursively check ancestors as well, which could cover the more complex scenario of A -> B -> C -> D -> A, but I kept the code here simple for brevity.