Spring Data MongoDb for class inheritance

Pavel Drobushevich picture Pavel Drobushevich · Jan 9, 2012 · Viewed 11.4k times · Source

I want to store different data to one collection in MongoDb and have Spring data beans with appropriate field..

Sorry, I've skipped details.

Parent bean:

class A
    int a

Childs:

class B extends A
    double b

class C extends A
    String c

So, there is following document in mongo

{a : 1, b : 2.3, c : "Test"}

When I fetch data, it is ok. But, when I call save method from CrudRepository for B, it rewrites all data and I lose C.

I know only one good option to create custom save method with incremental updates, such as

update.set("b", newvalue)...

but with reflection.

Do you have any other ideas?

Thanks in advance.

Answer

ltfishie picture ltfishie · Feb 18, 2012

For Spring-data MongoTemplate, in additional to the fields in your object, an additional field name _class is also saved which tells the template which class it is saving.
You will not be able to save an object correctly using another object's repository, regardless of the inheritance relationship.

The CrudRepository for Spring is essentially the Generic Dao pattern. Since all your dao implement the interface, and have the save method, you will be able to save any of the object by knowing which dao to use.

To do this, you can create a RepositoryFactory which is used to initial your repository, which offers an getRepository(Class<?> type) function that provide you with the appropriate repository for your class. Then you will be able to do something like:

repositoryFactory.getRepository(myType.getClass()).save(myType);

You can find more detail here: https://web.archive.org/web/20160722023804/http://www.rainydayinn.com:80/dev/dao-factory-and-generic-dao-wiring-in-spring/

If you want to store all your objects in the same collection, you can use the annotation @Document (collection="mycollection"). If you do not give a collection name, the default is to save each class in a separate collection according to the class name.