#8 - Add sample for @Meta usage.

Renamed the geo-spatial example to example only as it not only covers geo-spatial samples. Added advanced example to show the usage of the @Meta annotation.

Original pull request: #11.
This commit is contained in:
Christoph Strobl
2014-09-01 12:35:42 +02:00
committed by Oliver Gierke
parent ecadc65483
commit 6fb5259e37
13 changed files with 218 additions and 5 deletions

45
mongodb/example/pom.xml Normal file
View File

@@ -0,0 +1,45 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-mongodb-example</artifactId>
<name>Spring Data MongoDB - Example</name>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-mongodb-examples</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>${apt.version}</version>
<dependencies>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/annotations</outputDirectory>
<processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
<logOnlyOnError>true</logOnlyOnError>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.advanced;
import java.util.List;
import org.springframework.data.mongodb.repository.Meta;
import example.springdata.mongodb.customer.Customer;
import example.springdata.mongodb.customer.CustomerRepository;
/**
* Repository interface to manage {@link Customer} instances.
*
* @author Christoph Strobl
*/
public interface AdvancedRepository extends CustomerRepository {
String META_COMMENT = "s2gx-2014-rocks!";
/**
* Derived query using {@code $comment} meta attribute for quick lookup. <br />
* Have a look at the {@literal mongodb shell} and execute:
*
* <pre>
* <code>
* db['system.profile'].find({'query.$comment':'s2gx-2014-rocks!'})
* </code>
* </pre>
*
* @param firstname
* @return
*/
@Meta(comment = META_COMMENT)
List<Customer> findByFirstname(String firstname);
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.advanced;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoOperations;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
/**
* Test configuration to connect to a MongoDB named "test" and using a {@link MongoClient} with profiling enabled.
*
* @author Christoph Strobl
*/
@Configuration
@EnableAutoConfiguration
class ApplicationConfiguration {
static final String SYSTEM_PROFILE_DB = "system.profile";
@Autowired MongoOperations operations;
/**
* Initialize db instance with defaults.
*/
@PostConstruct
public void initializeWithDefaults() {
// Enable profiling
setProfilingLevel(2);
}
/**
* Clean up resources on shutdown
*/
@PreDestroy
public void cleanUpWhenShuttingDown() {
// Disable profiling
setProfilingLevel(0);
if (operations.collectionExists(SYSTEM_PROFILE_DB)) {
operations.dropCollection(SYSTEM_PROFILE_DB);
}
}
private void setProfilingLevel(int level) {
operations.executeCommand(new BasicDBObject("profile", level));
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.customer;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.data.geo.Point;
/**
* A domain object to capture addresses.
*
* @author Oliver Gierke
*/
@Getter
@RequiredArgsConstructor
public class Address {
private final Point location;
private String street;
private String zipCode;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.customer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import com.mongodb.MongoClient;
/**
* Test configuration to connect to a MongoDB named "test" and using a {@link MongoClient}. Also enables Spring Data
* repositories for MongoDB.
*
* @author Oliver Gierke
*/
@Configuration
@EnableAutoConfiguration
class ApplicationConfiguration {}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.customer;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.util.Assert;
/**
* An entity to represent a customer.
*
* @author Oliver Gierke
*/
@Data
@Document
public class Customer {
private ObjectId id;
private String firstname, lastname;
private Address address;
/**
* Creates a new {@link Customer} with the given firstname and lastname.
*
* @param firstname must not be {@literal null} or empty.
* @param lastname must not be {@literal null} or empty.
*/
public Customer(String firstname, String lastname) {
Assert.hasText(firstname, "Firstname must not be null or empty!");
Assert.hasText(lastname, "Lastname must not be null or empty!");
this.firstname = firstname;
this.lastname = lastname;
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.customer;
import java.util.List;
import org.bson.types.ObjectId;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.repository.CrudRepository;
/**
* Repository interface to manage {@link Customer} instances.
*
* @author Oliver Gierke
*/
public interface CustomerRepository extends CrudRepository<Customer, ObjectId> {
/**
* Derived query using dynamic sort information.
*
* @param lastname
* @param sort
* @return
*/
List<Customer> findByLastname(String lastname, Sort sort);
/**
* Showcase for a repository query using geo-spatial functionality.
*
* @param point
* @param distance
* @return
*/
GeoResults<Customer> findByAddressLocationNear(Point point, Distance distance);
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.advanced;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import example.springdata.mongodb.customer.Customer;
/**
* @author Christoph Strobl
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ApplicationConfiguration.class)
public class AdvancedIntegrationTests {
@Autowired AdvancedRepository repository;
@Autowired MongoOperations operations;
Customer dave, oliver, carter;
@Before
public void setUp() {
repository.deleteAll();
dave = repository.save(new Customer("Dave", "Matthews"));
oliver = repository.save(new Customer("Oliver August", "Matthews"));
carter = repository.save(new Customer("Carter", "Beauford"));
}
/**
* This test demonstrates usage of {@code $comment} {@link Meta} usage. One can also enable profiling using
* {@code --profile=2} when starting {@literal mongod}.
* <p>
* <strong>NOTE</strong>: Requires MongoDB v. 2.6.4+
*/
@Test
public void findByFirstnameUsingMetaAttributes() {
// execute derived finder method just to get the comment in the profile log
repository.findByFirstname(dave.getFirstname());
// execute another finder without meta attributes that should not be picked up
repository.findByLastname(dave.getLastname(), new Sort("firstname"));
DBCursor cursor = operations.getCollection(ApplicationConfiguration.SYSTEM_PROFILE_DB).find(
new BasicDBObject("query.$comment", AdvancedRepository.META_COMMENT));
while (cursor.hasNext()) {
DBObject dbo = cursor.next();
DBObject query = (DBObject) dbo.get("query");
assertThat(query.containsField("$comment"), is(true));
}
}
}

View File

@@ -0,0 +1,5 @@
/**
* Package showing usage of Spring Data abstractions for special (advanced) MongoDB operations.
*/
package example.springdata.mongodb.advanced;

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.mongodb.customer;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.index.GeospatialIndex;
import org.springframework.data.querydsl.QSort;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Integration test for {@link CustomerRepository}.
*
* @author Oliver Gierke
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ApplicationConfiguration.class)
public class CustomerRepositoryIntegrationTest {
@Autowired CustomerRepository repository;
@Autowired MongoOperations operations;
Customer dave, oliver, carter;
@Before
public void setUp() {
repository.deleteAll();
dave = repository.save(new Customer("Dave", "Matthews"));
oliver = repository.save(new Customer("Oliver August", "Matthews"));
carter = repository.save(new Customer("Carter", "Beauford"));
}
/**
* Test case to show that automatically generated ids are assigned to the domain objects.
*/
@Test
public void setsIdOnSave() {
Customer dave = repository.save(new Customer("Dave", "Matthews"));
assertThat(dave.getId(), is(notNullValue()));
}
/**
* Test case to show the usage of the Querydsl-specific {@link QSort} to define the sort order in a type-safe way.
*/
@Test
public void findCustomersUsingQuerydslSort() {
QCustomer customer = QCustomer.customer;
List<Customer> result = repository.findByLastname("Matthews", new QSort(customer.firstname.asc()));
assertThat(result, hasSize(2));
assertThat(result.get(0), is(dave));
assertThat(result.get(1), is(oliver));
}
/**
* Test case to show the usage of the geo-spatial APIs to lookup people within a given distance of a reference point.
*/
@Test
public void exposesGeoSpatialFunctionality() {
GeospatialIndex indexDefinition = new GeospatialIndex("address.location");
indexDefinition.getIndexOptions().put("min", -180);
indexDefinition.getIndexOptions().put("max", 180);
operations.indexOps(Customer.class).ensureIndex(indexDefinition);
Customer ollie = new Customer("Oliver", "Gierke");
ollie.setAddress(new Address(new Point(52.52548, 13.41477)));
ollie = repository.save(ollie);
Point referenceLocation = new Point(52.51790, 13.41239);
Distance oneKilometer = new Distance(1, Metrics.KILOMETERS);
GeoResults<Customer> result = repository.findByAddressLocationNear(referenceLocation, oneKilometer);
assertThat(result.getContent(), hasSize(1));
assertThat(result.getContent().get(0).getDistance(), is(new Distance(0.8624842788060683, Metrics.KILOMETERS)));
}
}

View File

@@ -0,0 +1,5 @@
/**
* Package showing basic usage of Spring Data MongoDB Repositories.
*/
package example.springdata.mongodb.customer;