Split up MongoDB example into two.

Split up the previously existing MongoDB example project in one for basic stuff, geo-spatial and Querydsl support as well as one on the aggregation framework. This will allow us to add other modules on particular focus areas going forward.
This commit is contained in:
Oliver Gierke
2014-07-31 14:10:46 +02:00
parent bb8711598e
commit 56ab6b4705
19 changed files with 111 additions and 46 deletions

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.shop;
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
public class ApplicationConfiguration {}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2013-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.shop;
import java.util.List;
import lombok.Value;
/**
* A DTO to represent invoices.
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
@Value
public class Invoice {
private final String orderId;
private final double taxAmount;
private final double netAmount;
private final double totalAmount;
private final List<LineItem> items;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2013-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.shop;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.data.annotation.PersistenceConstructor;
/**
* A line item.
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
@Data
@RequiredArgsConstructor(onConstructor = @__(@PersistenceConstructor))
public class LineItem {
private final String caption;
private final double price;
int quantity = 1;
public LineItem(String caption, double price, int quantity) {
this(caption, price);
this.quantity = quantity;
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2013-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.shop;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* An entity representing an {@link Order}. Note how we don't need any MongoDB mapping annotations as {@code id} is
* recognized as the id property by default.
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
@Data
@RequiredArgsConstructor(onConstructor = @__(@PersistenceConstructor))
@Document
public class Order {
private final String id;
private final String customerId;
private final Date orderDate;
private final List<LineItem> items;
/**
* Creates a new {@link Order} for the given customer id and order date.
*
* @param customerId
* @param orderDate
*/
public Order(String customerId, Date orderDate) {
this(null, customerId, orderDate, new ArrayList<LineItem>());
}
/**
* Adds a {@link LineItem} to the {@link Order}.
*
* @param item
* @return
*/
public Order addItem(LineItem item) {
this.items.add(item);
return this;
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2013-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.shop;
import org.springframework.data.repository.CrudRepository;
/**
* A repository interface assembling CRUD functionality as well as the API to invoke the methods implemented manually.
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
public interface OrderRepository extends CrudRepository<Order, String>, OrderRepositoryCustom {
}

View File

@@ -0,0 +1,32 @@
/*
* 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.shop;
/**
* The interface for repository functionality that will be implemented manually.
*
* @author Oliver Gierke
*/
interface OrderRepositoryCustom {
/**
* Creates an {@link Invoice} for the given {@link Order}.
*
* @param order must not be {@literal null}.
* @return
*/
Invoice getInvoiceFor(Order order);
}

View File

@@ -0,0 +1,67 @@
/*
* 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.shop;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
/**
* The manual implementation parts for {@link OrderRepository}. This will automatically be picked up by the Spring Data
* infrastructure as we follow the naming convention of extending the core repository interface's name with {@code Impl}
* .
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
class OrderRepositoryImpl implements OrderRepositoryCustom {
private final MongoOperations operations;
private double taxRate = 0.19;
/**
* The implementation uses the MongoDB aggregation framework support Spring Data provides as well as SpEL expressions
* to define arithmetical expressions. Note how we work with property names only and don't have to mitigate the nested
* {@code $_id} fields MongoDB usually requires.
*
* @see example.springdata.mongodb.shop.OrderRepositoryCustom#getInvoiceFor(example.springdata.mongodb.shop.Order)
*/
@Override
public Invoice getInvoiceFor(Order order) {
AggregationResults<Invoice> results = operations.aggregate(newAggregation(Order.class, //
match(where("id").is(order.getId())), //
unwind("items"), //
project("id", "customerId", "items") //
.andExpression("'$items.price' * '$items.quantity'").as("lineTotal"), //
group("id") //
.sum("lineTotal").as("netAmount") //
.addToSet("items").as("items"), //
project("id", "items", "netAmount") //
.and("orderId").previousOperation() //
.andExpression("netAmount * [0]", taxRate).as("taxAmount") //
.andExpression("netAmount * (1 + [0])", taxRate).as("totalAmount") //
), Invoice.class);
return results.getUniqueMappedResult();
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.shop;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.number.IsCloseTo.*;
import static org.junit.Assert.*;
import java.util.Date;
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.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Integration tests for {@link OrderRepository}.
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ApplicationConfiguration.class)
public class OrderRepositoryIntegrationTests {
@Autowired OrderRepository repository;
private final static LineItem product1 = new LineItem("p1", 1.23);
private final static LineItem product2 = new LineItem("p2", 0.87, 2);
private final static LineItem product3 = new LineItem("p3", 5.33);
@Before
public void setup() {
repository.deleteAll();
}
@Test
public void createsInvoiceViaAggregation() {
Order order = new Order("c42", new Date()).//
addItem(product1).addItem(product2).addItem(product3);
order = repository.save(order);
Invoice invoice = repository.getInvoiceFor(order);
assertThat(invoice, is(notNullValue()));
assertThat(invoice.getOrderId(), is(order.getId()));
assertThat(invoice.getNetAmount(), is(closeTo(8.3, 000001)));
assertThat(invoice.getTaxAmount(), is(closeTo(1.577, 000001)));
assertThat(invoice.getTotalAmount(), is(closeTo(9.877, 000001)));
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.data.mongodb.core.aggregation" level="debug" />
<root level="error">
<appender-ref ref="console" />
</root>
</configuration>