Page 1 of 3 123 LastLast
Results 1 to 10 of 22

Thread: Property bug in Spring Data MongoDB Support 1.0.0.M1

  1. #1
    Join Date
    Dec 2010
    Posts
    315

    Default Property bug in Spring Data MongoDB Support 1.0.0.M1

    I'm working on porting my tutorial
    Spring MVC 3: Using a Document-Oriented Database - MongoDB to use Spring Data Document - MongoDB Support 1.0.0.M1. However I think I've found a bug.

    The bug happens when your document (or your domain class) has an "id" property.

    Code:
    public class Person implements Serializable {
    
    	private String id;
    	private String firstName;
    	private String lastName;
    	private Double money;
    ...
    }
    Using plain MongoDB (no Spring Data support), to populate the Mongo with sample data, I call the init() method:

    Code:
    private void init() {
    		// Populate our MongoDB database
    
    		logger.debug("Init MongoDB users");
    		
    		// Drop existing collection
    		MongoDBFactory.getCollection("mydb","mycollection").drop();
    		// Retrieve collection. If not existing, create a new one
    		DBCollection coll = MongoDBFactory.getCollection("mydb","mycollection");
    		
    		// Create new object
    		BasicDBObject doc = new BasicDBObject();
    		// Generate random id using UUID type 4
    		// See http://en.wikipedia.org/wiki/Universally_unique_identifier
            doc.put("id", UUID.randomUUID().toString());
            doc.put("firstName", "John");
            doc.put("lastName", "Smith");
            doc.put("money", 1000);
            coll.insert(doc);
    		
            // Create new object
            doc = new BasicDBObject();
    		// Generate random id using UUID type 4
            doc.put("id", UUID.randomUUID().toString());
            doc.put("firstName", "Jane");
            doc.put("lastName", "Adams");
            doc.put("money", 2000);
            coll.insert(doc);
            
            // Create new object
            doc = new BasicDBObject();
    		// Generate random id using UUID type 4
            doc.put("id", UUID.randomUUID().toString());
            doc.put("firstName", "Jeff");
            doc.put("lastName", "Mayer");
            doc.put("money", 3000);
            coll.insert(doc);
    		
    	}
    Calling db.mycollection.find() on the Mongo console:
    Code:
    { "_id" : ObjectId("4d5e7b3bfdece02281f253a4"), "id" : "f1e6b8b2-9d68-495c-9d6e-b81cc35cf9bc", "firstName" : "John", "lastName" : "Smith", "money" : 1000 }
    { "_id" : ObjectId("4d5e7b3bfdece02282f253a4"), "id" : "39f6ebfb-10cf-4702-a5b8-8bc2489cebcc", "firstName" : "Jane", "lastName" : "Adams", "money" : 2000 }
    { "_id" : ObjectId("4d5e7b3bfdece02283f253a4"), "id" : "f4932004-c320-47e4-b4b3-7d07f3aaabb9", "firstName" : "Jeff", "lastName" : "Mayer", "money" : 3000 }
    Notice that all properties, id, firstName, lastName, and money are present. We also have another property "_id". This works fine.

    Now, I ported the code to use Spring Data MongoDb. To populate Mongo with data, I call the following init() method:
    Code:
    private void init() {
    		// Populate our MongoDB database
    
    		logger.debug("Init MongoDB users");
    		
    		// Drop existing collection
    		mongoTemplate.dropCollection("mycollection");
    		
    		// Create new object
    		Person p = new Person ();
    		p.setId(UUID.randomUUID().toString());
    		p.setFirstName("John");
    		p.setLastName("Smith");
    		p.setMoney(1000.0);
    		
    		// Insert to db
    	    mongoTemplate.insert("mycollection", p);
    
    	    // Create new object
    		p = new Person ();
    		p.setId(UUID.randomUUID().toString());
    		p.setFirstName("Jane");
    		p.setLastName("Adams");
    		p.setMoney(2000.0);
    		
    		// Insert to db
    	    mongoTemplate.insert("mycollection", p);
            
    	    // Create new object
    		p = new Person ();
    		p.setId(UUID.randomUUID().toString());
    		p.setFirstName("Jeff");
    		p.setLastName("Mayer");
    		p.setMoney(3000.0);
    		
    		// Insert to db
    	    mongoTemplate.insert("mycollection", p);
    	}
    Notice I used the template:
    Code:
    mongoTemplate.insert("mycollection", p);
    Calling db.mycollection.find() on the Mongo console:
    Code:
    { "_id" : "69133244-fcc0-42b2-aa59-308f00c75860", "firstName" : "John", "money" : 1000, "lastName" : "Smith" }
    { "_id" : "45d236ff-6a38-4767-a973-6f3d70ff2448", "firstName" : "Jane", "money" : 2000, "lastName" : "Adams" }
    { "_id" : "9dcba269-9ed5-45c6-887e-a2de8fec334d", "firstName" : "Jeff", "money" : 3000, "lastName" : "Mayer" }
    Notice the "id" property is gone. Actually it has been merged with the property "_id". In the original implementation, these are two separate properties.

    The real problem starts when you try to update and remove the item by "id". But the fundamental question is why the discrepancy between the two implementations?

    As a workaround, I had to name the property id to something different like "pid" and everything works as expected with Spring Data MongoDb.
    Last edited by skram; Feb 18th, 2011 at 08:25 AM.

  2. #2
    Join Date
    Dec 2010
    Posts
    315

    Default

    By the way here's the new tutorial that uses the Spring Data MongoDB 1.0.0.M1

    Spring Data - MongoDB Tutorial at http://krams915.blogspot.com/2011/02...-tutorial.html

  3. #3

    Default

    Thank you, skram. Regarding the id property, as far as I understand it, spring-data-document implementation hardcodes the "id" field to be the database id (_id in json). This is not good, we should add an annotation to specify which field is the database id field(e.g., @Id), so this problem will not appear. I think this would be covered in the JIRA ticket I filed: DATADOC-40 Add support for specifying attributes to entitties, e.g., collection name, field names, etc..
    Oruganti Shanker

  4. #4
    Join Date
    Dec 2010
    Posts
    315

    Default

    @oshankerShutter, thanks for verifying this problem. I thought I'm just having hallucinations I've checked the Spring Data for MongoDB source and you're right. Somehow the id is hard coded. I wouldn't call it bug or wrong behavior if the native MongoDB behaves exactly the same, but it behaves differently.

  5. #5
    Join Date
    Aug 2004
    Posts
    1,108

    Default

    You are right that the current bean property based SimpleMongoConverter maps any property named 'id' or '_id' to the Mongo _id field. We are considering other solutions for mapping and we could also add configuration for the SimpleMongoConverter to change the _id mapping behavior. I'll take a look at adding the latter for our M2 release.

    -Thomas
    Thomas Risberg
    SpringSource by Pivotal
    http://www.springsource.org

  6. #6
    Join Date
    Dec 2010
    Posts
    315

    Default

    @trisberg, thanks for the confirmation. I can't wait for the M2 release. I'm sure it's gonna be a great release as well

  7. #7
    Join Date
    Aug 2004
    Posts
    1,108

    Default

    I'm just curious why it's important to maintain a separate id and _id property. I'd assume that if you have a unique id property you could use that for the _id field and skip the _id property of type ObjectId. Am I missing something?

    -Thomas
    Thomas Risberg
    SpringSource by Pivotal
    http://www.springsource.org

  8. #8

    Default

    We need only one id - the issue is that it must not be hardcoded to be named "id" - the user must be able to use an annotation to say that a field named "x" is actually the id field (a la @id in JPA). This is important for projects which want to port existing code (say, currently using morphia) to spring-data-document whithout having to rewrite all their entities and supporting code.
    Oruganti Shanker

  9. #9
    Join Date
    Aug 2004
    Posts
    1,108

    Default

    I agree and we are working on a more advanced mapping solution for the M2 release. The current SimpleMongoConverter only handles basic JavaBeans and relies on either an _id or id property. We'll try to add some configurability to the SimpleMongoConverter but annotation support is planned for the more advanced mapping solution that we are just starting to work on.
    Thomas Risberg
    SpringSource by Pivotal
    http://www.springsource.org

  10. #10
    Join Date
    Jul 2006
    Location
    Lamar, Missouri USA
    Posts
    36

    Default

    The M2 mapping support will allow you to put an @Id annotation on any field (or it will look for an ObjectId or String named either "id" or "_id") but that won't put a property into the document named by that field name.

    For example, given:

    Code:
    class Person {
      @Id
      private String empId;
    }
    I won't have a document that looks like:

    Code:
    {
      "_id": ObjectId("blahblahblah"),
      "empId": "blahblahblah",
      ...other properties...
    }
    It will transliterate the "empId" property to "_id". Is this okay? Or are you wanting both an "_id" and an "empId" property to appear on the document?
    Jon Brisbin
    SpringSource
    http://www.springsource.com

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •