Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MongoDB data can not fetch @DBRef objects with "find" query

There is an object a classic POJO as below:

@Document
public class MyPojo {
  @DBRef
  @Field("otherPojo")
  private List<OtherPojo> otherPojos;
}

And OtherPojo.java:

public class OtherPojo{
  @Id
  private ObjectId _id;
  private String someOtherFields;
}

I can not cascade-save these, but I'm getting over it by saving DBRefs first and then saving my POJO list, but still when I try to fetch all list or querying some of them with below code:

Query query = new Query( Criteria.where( "myPojo.blabla" ).is( "blabla" ) );
List<MyPojo> resultList = mongoTemplate.find( query, MyPojo.class, "myCollection" );

it returns me with a list of null DBrefs, it counts true. For example: there are saved 10 DBRefs it returns 10 null object in it, but its primitive types and other types that aren't a DBRref are all non-null. How can i handle this ?

I save my objects as below:

for (MyPojo pojo : somePojoList) {
    for (OtherPojo otherPojo : pojo.getOtherPojos()) {
        mongoTemplate.save(otherPojo, "myCollection");
    }
}

// ...

mongoTemplate.insert( myPojoList, "myCollection" );

EDIT: OK, now I know if I do not specify a collection name when I'm saving otherPojos, I can fetch them (thanks to @jmen7070). But I have to write myCollection there because I'm dropping and re-creating them always. That's a use-case. So how can I say "find method to use same collection to fetch DBRefs"?

like image 729
Sercan Ozdemir Avatar asked Nov 01 '22 00:11

Sercan Ozdemir


1 Answers

As you can see from docs:

The mapping framework does not handle cascading saves. If you change an Account object that is referenced by a Person object, you must save the Account object separately. Calling save on the Person object will not automatically save the Account objects in the property accounts.

So, first, you have to save each object of the otherPojos list. After that you can save MyPojo instance:

MyPojo pojo = new MyPojo();
OtherPojo otherPojo = new OtherPojo();
OtherPojo otherPojo1 = new OtherPojo();

pojo.setOtherPojos(Arrays.asList(otherPojo, otherPojo1));

mongoTemplate.save(otherPojo);
mongoTemplate.save(otherPojo1);

mongoTemplate.save(pojo);

UPDATED: You saved a objects:

for( MyPojo pojo : somePojoList ){
            for( OtherPojo otherPojo : pojo.getOtherPojos() ){
                mongoTemplate.save( otherPojo,collectionname );
            }
        }

All otherPojo objects will be saved in collection with name "collectionName"..

but your myPojo objects have a $ref to an otherPojo collection..

"otherPojo" : [ 
        {
            "$ref" : "otherPojo",
            "$id" : ObjectId("535f9100ad52e59815755cef")
        }, 
        {
            "$ref" : "otherPojo",
            "$id" : ObjectId("535f9101ad52e59815755cf0")
        }
    ]

So, "collectionname" variable

 mongoTemplate.save( otherPojo,collectionname );

must be "otherPojo".

To avoid confusion, I propose to specify a collection for saving OtherPojo objects with @Doucument annotation:

@Document(collection="otherPojos")
public class OtherPojo{

@Id
private ObjectId _id;
private String someOtherFields;

}

And to save otherPojo objects by using a overloaded save() method of mongoTemplate

mongoTemplate.save( otherPojo );

In this way , you will have a valid $ref for myPojo documents

UPDATE 2:

In this case, you want to store parents and childs object in same collection.

To achieve this you can use this approach

like image 86
jmen7070 Avatar answered Nov 15 '22 04:11

jmen7070