Pattern for saving objects

Is there a pattern for saving objects to mongodb without persisting properties that didnt change from the constructor?

I have a document that varies a lot in its content, and if I create a java object from a json and then save it to the database it will contain a lot of unnecessary fields.

Is there already a pattern/best practice to do this or should I keep track of every property to see if it has changed?

thanks

Hi @apachai_54593,

To better understand your query, can you please elaborate more, like if I have a document like below:

   { name: "John", age: 56, company: "MongoDB", hobbies: ["swimming"]}  

And if only one property like hobbies is changing, then all fields will be sent to the database and that is unnecessary, is that right?

Kanika

Hi Kanika.

My problem is having properties that exist in some documents but not in others.In your example, suppose company or hobbies didnt exist from John. But the POJO created to represent a document has both these properties. How do I keep from saving those properties that didnt exist for a particular document to be saved in the database.

My real case comes from this document

https://wiki.guildwars2.com/wiki/API:2/items

Thats the description of the documents returned by the api for items .
Items have a sub document called details, that can vary from having 1 property to twenty properties. I modeled the POJO to have all 20 properties, but if I use it to persist all 20 properties will be saved, even if the original json document only had 1.

So im wondering if there is a way to deal with this situation. I ended not using pojos, and saving the raw document instead.

Thanks

Hi @apachai_54593,

Please take a look at the documentation link below:

It will give you an idea about how to insert a document which do not create all the fields defined in the already created POJO.

Please let me know, if you have any questions.

Thanks,
Sonali

Thank you Kanika, I will change what I had to use PojoRegistry. I did that code before doing this course and parsed the documents with another library.

1 Like

Hi Kanika and Sonali.

I changed my code to use the codec registry in the initialization of a dao class. I was using a simple repository without any implementation before.

@Autowired
public ItemDao(MongoClient mongoClient, @Value("${spring.data.mongodb.database}") String databaseName) {
    super(mongoClient, databaseName);
    this.pojoCodecRegistry =
            fromRegistries(
                    MongoClientSettings.getDefaultCodecRegistry(),
                    fromProviders(PojoCodecProvider.builder().automatic(true).build()));
    itemCollection = db.getCollection(ITEM_COLLECTION,Item.class).withCodecRegistry(pojoCodecRegistry);
}

After that I did a test reading a document from the database and the saving it again with another _id.

I ran this test
@Test
public void cloneItemTest() {
int id = 15;
String expectedName = “Abomination Hammer”;
this.dao = new ItemDao(mongoClient, databaseName);
Item item = dao.getItem(id);
item.setId(9999999);
dao.addItem(item);
assertEquals(expectedName, item.getName(),“Item name does not match expected”);
}

After reading an item into a pojo and saving it again, the detail sub document in the database had new
properties added , having the default values java assigned to it.

// Original Item
{
   "_id":{"$numberInt":"15"},
   "name":"Abomination Hammer",
   "type":"Weapon",
   "level":{"$numberInt":"0"},
   "rarity":"Fine",
   "vendor_value":{"$numberInt":"0"},
   "default_skin":{"$numberInt":"5014"},
   "game_types":["Activity","Wvw","Dungeon","Pve"],
   "flags":["NoSell","SoulbindOnAcquire","SoulBindOnUse"],
   "restrictions":[],
   "chat_link":"[&AgEPAAAA]",
   "icon":"https://render.guildwars2.com/file/E8507FFB6CF3C9094A69956344CEDBD9B47D95B6/434872.png",
"details":{
	"type":"Hammer",
	"damage_type":"Physical",
	"min_power":{"$numberInt":"146"},
	"max_power":{"$numberInt":"165"},
	"defense":{"$numberInt":"0"},
	"infusion_slots":[],
	"infix_upgrade":{
		"id":{
			"$numberInt":"112"},
			"attributes":[]
	},
	"secondary_suffix_item_id":""}
}

// Cloned item after saving
{"_id":{"$numberLong":“9999999”},
“chat_link”:"[&AgEPAAAA]",
“default_skin”:{"$numberInt":“5014”},
“details”:{
"apply_count":{"$numberInt":“0”},
** “charges”:{"$numberInt":“0”},“color_id”:{"$numberInt":“0”},**
“damage_type”:“Physical”,
“defense”:{"$numberInt":“0”},
"duration_ms":{"$numberInt":“0”},
“guild_upgrade_id”:{"$numberLong":“0”},
“infix_upgrade”:{
“_id”:{"$numberLong":“0”},
“attributes”:
},
“infusion_slots”:,
“max_power”:{"$numberInt":“165”},
“min_power”:{"$numberInt":“146”},
"minipet_id":{"$numberInt":“0”},
“no_sell_or_sort”:false,
“recipe_id”:{"$numberLong":“0”},
“secondary_suffix_item_id”:"",
"size":{"$numberInt":“0”},
** “suffix_item_id”:{"$numberLong":“0”},**
“type”:“Hammer”
},
“flags”:[“NoSell”,“SoulbindOnAcquire”,“SoulBindOnUse”],
“game_types”:[“Activity”,“Wvw”,“Dungeon”,“Pve”],
“icon”:“https://render.guildwars2.com/file/E8507FFB6CF3C9094A69956344CEDBD9B47D95B6/434872.png”,
“level”:{"$numberInt":“0”},
“name”:“Abomination Hammer”,
“rarity”:“Fine”,
“restrictions”:,
“type”:“Weapon”,
“vendor_value”:{"$numberInt":“0”}
}

Should I stop using pojo to save objects to the database and use documents instead?

I tried to edit the json part to indent but although it shows indented in the preview It has no effect on the final outcome. I highlighted some of the properties that got added in the details part of the item.

I use the html pre tag which preserve all indentation as shown below:

{
    'my field name' : 'my value' 
}

Highlighting was a good idea and make it clear. I suspect that this is the standard behaviour for default values. But I hope somebody with more experience with POJO will bring some clarification. Personally, I do not use POJOs as I like the flexibility to work with plain documents.