@Test
  public void testUsingUpdateWithMultipleSet() throws Exception {

    template.remove(new Query(), PersonWithIdPropertyOfTypeObjectId.class);

    PersonWithIdPropertyOfTypeObjectId p1 = new PersonWithIdPropertyOfTypeObjectId();
    p1.setFirstName("Sven");
    p1.setAge(11);
    template.insert(p1);
    PersonWithIdPropertyOfTypeObjectId p2 = new PersonWithIdPropertyOfTypeObjectId();
    p2.setFirstName("Mary");
    p2.setAge(21);
    template.insert(p2);

    Update u = new Update().set("firstName", "Bob").set("age", 10);

    WriteResult wr = template.updateMulti(new Query(), u, PersonWithIdPropertyOfTypeObjectId.class);

    assertThat(wr.getN(), is(2));

    Query q1 = new Query(Criteria.where("age").in(11, 21));
    List<PersonWithIdPropertyOfTypeObjectId> r1 =
        template.find(q1, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(r1.size(), is(0));
    Query q2 = new Query(Criteria.where("age").is(10));
    List<PersonWithIdPropertyOfTypeObjectId> r2 =
        template.find(q2, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(r2.size(), is(2));
    for (PersonWithIdPropertyOfTypeObjectId p : r2) {
      assertThat(p.getAge(), is(10));
      assertThat(p.getFirstName(), is("Bob"));
    }
  }
  @Test
  public void testRemovingDocument() throws Exception {

    PersonWithIdPropertyOfTypeObjectId p1 = new PersonWithIdPropertyOfTypeObjectId();
    p1.setFirstName("Sven_to_be_removed");
    p1.setAge(51);
    template.insert(p1);

    Query q1 = new Query(Criteria.where("id").is(p1.getId()));
    PersonWithIdPropertyOfTypeObjectId found1 =
        template.findOne(q1, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(found1, notNullValue());
    Query _q = new Query(Criteria.where("_id").is(p1.getId()));
    template.remove(_q, PersonWithIdPropertyOfTypeObjectId.class);
    PersonWithIdPropertyOfTypeObjectId notFound1 =
        template.findOne(q1, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(notFound1, nullValue());

    PersonWithIdPropertyOfTypeObjectId p2 = new PersonWithIdPropertyOfTypeObjectId();
    p2.setFirstName("Bubba_to_be_removed");
    p2.setAge(51);
    template.insert(p2);

    Query q2 = new Query(Criteria.where("id").is(p2.getId()));
    PersonWithIdPropertyOfTypeObjectId found2 =
        template.findOne(q2, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(found2, notNullValue());
    template.remove(q2, PersonWithIdPropertyOfTypeObjectId.class);
    PersonWithIdPropertyOfTypeObjectId notFound2 =
        template.findOne(q2, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(notFound2, nullValue());
  }
  /** @see DATADOC-240, DATADOC-212 */
  @Test
  public void updatesObjectIdsCorrectly() {

    PersonWithIdPropertyOfTypeObjectId person = new PersonWithIdPropertyOfTypeObjectId();
    person.setId(new ObjectId());
    person.setFirstName("Dave");

    template.save(person);
    template.updateFirst(
        query(where("id").is(person.getId())),
        update("firstName", "Carter"),
        PersonWithIdPropertyOfTypeObjectId.class);

    PersonWithIdPropertyOfTypeObjectId result =
        template.findById(person.getId(), PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(result, is(notNullValue()));
    assertThat(result.getId(), is(person.getId()));
    assertThat(result.getFirstName(), is("Carter"));
  }
  @Test
  public void testWriteConcernResolver() {

    PersonWithIdPropertyOfTypeObjectId person = new PersonWithIdPropertyOfTypeObjectId();
    person.setId(new ObjectId());
    person.setFirstName("Dave");

    template.setWriteConcern(WriteConcern.NONE);
    template.save(person);
    WriteResult result =
        template.updateFirst(
            query(where("id").is(person.getId())),
            update("firstName", "Carter"),
            PersonWithIdPropertyOfTypeObjectId.class);
    WriteConcern lastWriteConcern = result.getLastConcern();
    assertThat(lastWriteConcern, equalTo(WriteConcern.NONE));

    FsyncSafeWriteConcernResolver resolver = new FsyncSafeWriteConcernResolver();
    template.setWriteConcernResolver(resolver);
    Query q = query(where("_id").is(person.getId()));
    Update u = update("firstName", "Carter");
    result = template.updateFirst(q, u, PersonWithIdPropertyOfTypeObjectId.class);
    lastWriteConcern = result.getLastConcern();
    assertThat(lastWriteConcern, equalTo(WriteConcern.FSYNC_SAFE));

    MongoAction lastMongoAction = resolver.getMongoAction();
    assertThat(lastMongoAction.getCollectionName(), is("personWithIdPropertyOfTypeObjectId"));
    assertThat(lastMongoAction.getDefaultWriteConcern(), equalTo(WriteConcern.NONE));
    assertThat(lastMongoAction.getDocument(), notNullValue());
    assertThat(
        lastMongoAction.getEntityClass().toString(),
        is(PersonWithIdPropertyOfTypeObjectId.class.toString()));
    assertThat(lastMongoAction.getMongoActionOperation(), is(MongoActionOperation.UPDATE));
    assertThat(lastMongoAction.getQuery(), equalTo(q.getQueryObject()));
    assertThat(lastMongoAction.getDocument(), equalTo(u.getUpdateObject()));
  }
  @Test
  public void testUsingAnOrQuery() throws Exception {

    template.remove(new Query(), PersonWithIdPropertyOfTypeObjectId.class);

    PersonWithIdPropertyOfTypeObjectId p1 = new PersonWithIdPropertyOfTypeObjectId();
    p1.setFirstName("Sven");
    p1.setAge(11);
    template.insert(p1);
    PersonWithIdPropertyOfTypeObjectId p2 = new PersonWithIdPropertyOfTypeObjectId();
    p2.setFirstName("Mary");
    p2.setAge(21);
    template.insert(p2);
    PersonWithIdPropertyOfTypeObjectId p3 = new PersonWithIdPropertyOfTypeObjectId();
    p3.setFirstName("Ann");
    p3.setAge(31);
    template.insert(p3);
    PersonWithIdPropertyOfTypeObjectId p4 = new PersonWithIdPropertyOfTypeObjectId();
    p4.setFirstName("John");
    p4.setAge(41);
    template.insert(p4);

    Query orQuery =
        new Query(new Criteria().orOperator(where("age").in(11, 21), where("age").is(31)));
    List<PersonWithIdPropertyOfTypeObjectId> results =
        template.find(orQuery, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(results.size(), is(3));
    for (PersonWithIdPropertyOfTypeObjectId p : results) {
      assertThat(p.getAge(), isOneOf(11, 21, 31));
    }
  }
  @Test
  public void testUsingRegexQueryWithOptions() throws Exception {

    template.remove(new Query(), PersonWithIdPropertyOfTypeObjectId.class);

    PersonWithIdPropertyOfTypeObjectId p1 = new PersonWithIdPropertyOfTypeObjectId();
    p1.setFirstName("Sven");
    p1.setAge(11);
    template.insert(p1);
    PersonWithIdPropertyOfTypeObjectId p2 = new PersonWithIdPropertyOfTypeObjectId();
    p2.setFirstName("Mary");
    p2.setAge(21);
    template.insert(p2);
    PersonWithIdPropertyOfTypeObjectId p3 = new PersonWithIdPropertyOfTypeObjectId();
    p3.setFirstName("Ann");
    p3.setAge(31);
    template.insert(p3);
    PersonWithIdPropertyOfTypeObjectId p4 = new PersonWithIdPropertyOfTypeObjectId();
    p4.setFirstName("samantha");
    p4.setAge(41);
    template.insert(p4);

    Query q1 = new Query(Criteria.where("firstName").regex("S.*"));
    List<PersonWithIdPropertyOfTypeObjectId> results1 =
        template.find(q1, PersonWithIdPropertyOfTypeObjectId.class);
    Query q2 = new Query(Criteria.where("firstName").regex("S.*", "i"));
    List<PersonWithIdPropertyOfTypeObjectId> results2 =
        template.find(q2, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(results1.size(), is(1));
    assertThat(results2.size(), is(2));
  }
  @Test
  public void testUsingInQueryWithList() throws Exception {

    template.remove(new Query(), PersonWithIdPropertyOfTypeObjectId.class);

    PersonWithIdPropertyOfTypeObjectId p1 = new PersonWithIdPropertyOfTypeObjectId();
    p1.setFirstName("Sven");
    p1.setAge(11);
    template.insert(p1);
    PersonWithIdPropertyOfTypeObjectId p2 = new PersonWithIdPropertyOfTypeObjectId();
    p2.setFirstName("Mary");
    p2.setAge(21);
    template.insert(p2);
    PersonWithIdPropertyOfTypeObjectId p3 = new PersonWithIdPropertyOfTypeObjectId();
    p3.setFirstName("Ann");
    p3.setAge(31);
    template.insert(p3);
    PersonWithIdPropertyOfTypeObjectId p4 = new PersonWithIdPropertyOfTypeObjectId();
    p4.setFirstName("John");
    p4.setAge(41);
    template.insert(p4);

    List<Integer> l1 = new ArrayList<Integer>();
    l1.add(11);
    l1.add(21);
    l1.add(41);
    Query q1 = new Query(Criteria.where("age").in(l1));
    List<PersonWithIdPropertyOfTypeObjectId> results1 =
        template.find(q1, PersonWithIdPropertyOfTypeObjectId.class);
    Query q2 = new Query(Criteria.where("age").in(l1.toArray()));
    List<PersonWithIdPropertyOfTypeObjectId> results2 =
        template.find(q2, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(results1.size(), is(3));
    assertThat(results2.size(), is(3));
    try {
      List<Integer> l2 = new ArrayList<Integer>();
      l2.add(31);
      Query q3 = new Query(Criteria.where("age").in(l1, l2));
      template.find(q3, PersonWithIdPropertyOfTypeObjectId.class);
      Assert.fail("Should have trown an InvalidDocumentStoreApiUsageException");
    } catch (InvalidMongoDbApiUsageException e) {
    }
  }
  @Test
  public void testUsingAnInQueryWithObjectId() throws Exception {

    template.remove(new Query(), PersonWithIdPropertyOfTypeObjectId.class);

    PersonWithIdPropertyOfTypeObjectId p1 = new PersonWithIdPropertyOfTypeObjectId();
    p1.setFirstName("Sven");
    p1.setAge(11);
    template.insert(p1);
    PersonWithIdPropertyOfTypeObjectId p2 = new PersonWithIdPropertyOfTypeObjectId();
    p2.setFirstName("Mary");
    p2.setAge(21);
    template.insert(p2);
    PersonWithIdPropertyOfTypeObjectId p3 = new PersonWithIdPropertyOfTypeObjectId();
    p3.setFirstName("Ann");
    p3.setAge(31);
    template.insert(p3);
    PersonWithIdPropertyOfTypeObjectId p4 = new PersonWithIdPropertyOfTypeObjectId();
    p4.setFirstName("John");
    p4.setAge(41);
    template.insert(p4);

    Query q1 = new Query(Criteria.where("age").in(11, 21, 41));
    List<PersonWithIdPropertyOfTypeObjectId> results1 =
        template.find(q1, PersonWithIdPropertyOfTypeObjectId.class);
    Query q2 = new Query(Criteria.where("firstName").in("Ann", "Mary"));
    List<PersonWithIdPropertyOfTypeObjectId> results2 =
        template.find(q2, PersonWithIdPropertyOfTypeObjectId.class);
    Query q3 = new Query(Criteria.where("id").in(p3.getId()));
    List<PersonWithIdPropertyOfTypeObjectId> results3 =
        template.find(q3, PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(results1.size(), is(3));
    assertThat(results2.size(), is(2));
    assertThat(results3.size(), is(1));
  }
  private void testProperHandlingOfDifferentIdTypes(MongoTemplate mongoTemplate) throws Exception {

    // String id - generated
    PersonWithIdPropertyOfTypeString p1 = new PersonWithIdPropertyOfTypeString();
    p1.setFirstName("Sven_1");
    p1.setAge(22);
    // insert
    mongoTemplate.insert(p1);
    // also try save
    mongoTemplate.save(p1);
    assertThat(p1.getId(), notNullValue());
    PersonWithIdPropertyOfTypeString p1q =
        mongoTemplate.findOne(
            new Query(where("id").is(p1.getId())), PersonWithIdPropertyOfTypeString.class);
    assertThat(p1q, notNullValue());
    assertThat(p1q.getId(), is(p1.getId()));
    checkCollectionContents(PersonWithIdPropertyOfTypeString.class, 1);

    // String id - provided
    PersonWithIdPropertyOfTypeString p2 = new PersonWithIdPropertyOfTypeString();
    p2.setFirstName("Sven_2");
    p2.setAge(22);
    p2.setId("TWO");
    // insert
    mongoTemplate.insert(p2);
    // also try save
    mongoTemplate.save(p2);
    assertThat(p2.getId(), notNullValue());
    PersonWithIdPropertyOfTypeString p2q =
        mongoTemplate.findOne(
            new Query(where("id").is(p2.getId())), PersonWithIdPropertyOfTypeString.class);
    assertThat(p2q, notNullValue());
    assertThat(p2q.getId(), is(p2.getId()));
    checkCollectionContents(PersonWithIdPropertyOfTypeString.class, 2);

    // String _id - generated
    PersonWith_idPropertyOfTypeString p3 = new PersonWith_idPropertyOfTypeString();
    p3.setFirstName("Sven_3");
    p3.setAge(22);
    // insert
    mongoTemplate.insert(p3);
    // also try save
    mongoTemplate.save(p3);
    assertThat(p3.get_id(), notNullValue());
    PersonWith_idPropertyOfTypeString p3q =
        mongoTemplate.findOne(
            new Query(where("_id").is(p3.get_id())), PersonWith_idPropertyOfTypeString.class);
    assertThat(p3q, notNullValue());
    assertThat(p3q.get_id(), is(p3.get_id()));
    checkCollectionContents(PersonWith_idPropertyOfTypeString.class, 1);

    // String _id - provided
    PersonWith_idPropertyOfTypeString p4 = new PersonWith_idPropertyOfTypeString();
    p4.setFirstName("Sven_4");
    p4.setAge(22);
    p4.set_id("FOUR");
    // insert
    mongoTemplate.insert(p4);
    // also try save
    mongoTemplate.save(p4);
    assertThat(p4.get_id(), notNullValue());
    PersonWith_idPropertyOfTypeString p4q =
        mongoTemplate.findOne(
            new Query(where("_id").is(p4.get_id())), PersonWith_idPropertyOfTypeString.class);
    assertThat(p4q, notNullValue());
    assertThat(p4q.get_id(), is(p4.get_id()));
    checkCollectionContents(PersonWith_idPropertyOfTypeString.class, 2);

    // ObjectId id - generated
    PersonWithIdPropertyOfTypeObjectId p5 = new PersonWithIdPropertyOfTypeObjectId();
    p5.setFirstName("Sven_5");
    p5.setAge(22);
    // insert
    mongoTemplate.insert(p5);
    // also try save
    mongoTemplate.save(p5);
    assertThat(p5.getId(), notNullValue());
    PersonWithIdPropertyOfTypeObjectId p5q =
        mongoTemplate.findOne(
            new Query(where("id").is(p5.getId())), PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(p5q, notNullValue());
    assertThat(p5q.getId(), is(p5.getId()));
    checkCollectionContents(PersonWithIdPropertyOfTypeObjectId.class, 1);

    // ObjectId id - provided
    PersonWithIdPropertyOfTypeObjectId p6 = new PersonWithIdPropertyOfTypeObjectId();
    p6.setFirstName("Sven_6");
    p6.setAge(22);
    p6.setId(new ObjectId());
    // insert
    mongoTemplate.insert(p6);
    // also try save
    mongoTemplate.save(p6);
    assertThat(p6.getId(), notNullValue());
    PersonWithIdPropertyOfTypeObjectId p6q =
        mongoTemplate.findOne(
            new Query(where("id").is(p6.getId())), PersonWithIdPropertyOfTypeObjectId.class);
    assertThat(p6q, notNullValue());
    assertThat(p6q.getId(), is(p6.getId()));
    checkCollectionContents(PersonWithIdPropertyOfTypeObjectId.class, 2);

    // ObjectId _id - generated
    PersonWith_idPropertyOfTypeObjectId p7 = new PersonWith_idPropertyOfTypeObjectId();
    p7.setFirstName("Sven_7");
    p7.setAge(22);
    // insert
    mongoTemplate.insert(p7);
    // also try save
    mongoTemplate.save(p7);
    assertThat(p7.get_id(), notNullValue());
    PersonWith_idPropertyOfTypeObjectId p7q =
        mongoTemplate.findOne(
            new Query(where("_id").is(p7.get_id())), PersonWith_idPropertyOfTypeObjectId.class);
    assertThat(p7q, notNullValue());
    assertThat(p7q.get_id(), is(p7.get_id()));
    checkCollectionContents(PersonWith_idPropertyOfTypeObjectId.class, 1);

    // ObjectId _id - provided
    PersonWith_idPropertyOfTypeObjectId p8 = new PersonWith_idPropertyOfTypeObjectId();
    p8.setFirstName("Sven_8");
    p8.setAge(22);
    p8.set_id(new ObjectId());
    // insert
    mongoTemplate.insert(p8);
    // also try save
    mongoTemplate.save(p8);
    assertThat(p8.get_id(), notNullValue());
    PersonWith_idPropertyOfTypeObjectId p8q =
        mongoTemplate.findOne(
            new Query(where("_id").is(p8.get_id())), PersonWith_idPropertyOfTypeObjectId.class);
    assertThat(p8q, notNullValue());
    assertThat(p8q.get_id(), is(p8.get_id()));
    checkCollectionContents(PersonWith_idPropertyOfTypeObjectId.class, 2);

    // Integer id - provided
    PersonWithIdPropertyOfTypeInteger p9 = new PersonWithIdPropertyOfTypeInteger();
    p9.setFirstName("Sven_9");
    p9.setAge(22);
    p9.setId(Integer.valueOf(12345));
    // insert
    mongoTemplate.insert(p9);
    // also try save
    mongoTemplate.save(p9);
    assertThat(p9.getId(), notNullValue());
    PersonWithIdPropertyOfTypeInteger p9q =
        mongoTemplate.findOne(
            new Query(where("id").in(p9.getId())), PersonWithIdPropertyOfTypeInteger.class);
    assertThat(p9q, notNullValue());
    assertThat(p9q.getId(), is(p9.getId()));
    checkCollectionContents(PersonWithIdPropertyOfTypeInteger.class, 1);

    // int id - provided
    PersonWithIdPropertyOfPrimitiveInt p10 = new PersonWithIdPropertyOfPrimitiveInt();
    p10.setFirstName("Sven_10");
    p10.setAge(22);
    p10.setId(12345);
    // insert
    mongoTemplate.insert(p10);
    // also try save
    mongoTemplate.save(p10);
    assertThat(p10.getId(), notNullValue());
    PersonWithIdPropertyOfPrimitiveInt p10q =
        mongoTemplate.findOne(
            new Query(where("id").in(p10.getId())), PersonWithIdPropertyOfPrimitiveInt.class);
    assertThat(p10q, notNullValue());
    assertThat(p10q.getId(), is(p10.getId()));
    checkCollectionContents(PersonWithIdPropertyOfPrimitiveInt.class, 1);

    // Long id - provided
    PersonWithIdPropertyOfTypeLong p11 = new PersonWithIdPropertyOfTypeLong();
    p11.setFirstName("Sven_9");
    p11.setAge(22);
    p11.setId(Long.valueOf(12345L));
    // insert
    mongoTemplate.insert(p11);
    // also try save
    mongoTemplate.save(p11);
    assertThat(p11.getId(), notNullValue());
    PersonWithIdPropertyOfTypeLong p11q =
        mongoTemplate.findOne(
            new Query(where("id").in(p11.getId())), PersonWithIdPropertyOfTypeLong.class);
    assertThat(p11q, notNullValue());
    assertThat(p11q.getId(), is(p11.getId()));
    checkCollectionContents(PersonWithIdPropertyOfTypeLong.class, 1);

    // long id - provided
    PersonWithIdPropertyOfPrimitiveLong p12 = new PersonWithIdPropertyOfPrimitiveLong();
    p12.setFirstName("Sven_10");
    p12.setAge(22);
    p12.setId(12345L);
    // insert
    mongoTemplate.insert(p12);
    // also try save
    mongoTemplate.save(p12);
    assertThat(p12.getId(), notNullValue());
    PersonWithIdPropertyOfPrimitiveLong p12q =
        mongoTemplate.findOne(
            new Query(where("id").in(p12.getId())), PersonWithIdPropertyOfPrimitiveLong.class);
    assertThat(p12q, notNullValue());
    assertThat(p12q.getId(), is(p12.getId()));
    checkCollectionContents(PersonWithIdPropertyOfPrimitiveLong.class, 1);
  }