committed by
Greg L. Turnquist
parent
83cd9e2d5a
commit
7e50e0b612
@@ -2,9 +2,10 @@
|
||||
|
||||
This project contains examples for:
|
||||
|
||||
* Derived finder and geo spatial queries using a `Repository` interface.
|
||||
* Derived query method and geospatial queries using a `Repository` interface.
|
||||
* Usage of property-specific converters.
|
||||
* `EntityCallback` API usage for before convert/save interaction.
|
||||
* Result projections for DTOs and interface types.
|
||||
* Query metadata.
|
||||
* Result projections for DTOs and interface types.
|
||||
* Query metadata.
|
||||
* Unwrapping entities into the parent document.
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data.examples</groupId>
|
||||
<artifactId>spring-data-mongodb-example-utils</artifactId>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2014-2021 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
|
||||
*
|
||||
* https://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.converters;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.geo.Point;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* A domain object to capture addresses.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
public class Address {
|
||||
|
||||
private final Point location;
|
||||
private String street;
|
||||
private String zipCode;
|
||||
|
||||
Address(@JsonProperty("location") Map<String, Double> location, @JsonProperty("street") String street,
|
||||
@JsonProperty("zipCode") String zipCode) {
|
||||
|
||||
this.location = new Point(location.get("x"), location.get("y"));
|
||||
this.street = street;
|
||||
this.zipCode = zipCode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2022 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.converters;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConversionContext;
|
||||
import org.springframework.data.mongodb.core.convert.MongoValueConverter;
|
||||
|
||||
/**
|
||||
* {@link MongoValueConverter} to write only the {@link Address#location} into a MongoDB {@link Document}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AddressDocumentConverter implements MongoValueConverter<Address, Document> {
|
||||
|
||||
@Override
|
||||
public Address read(Document value, MongoConversionContext context) {
|
||||
|
||||
Point point = new Point(context.read(value.get("x"), Double.class), context.read(value.get("y"), Double.class));
|
||||
|
||||
return new Address(point);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document write(Address value, MongoConversionContext context) {
|
||||
|
||||
Document document = new Document();
|
||||
document.put("x", value.getLocation().getX());
|
||||
document.put("y", value.getLocation().getY());
|
||||
|
||||
return document;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2022 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.converters;
|
||||
|
||||
import org.springframework.data.mongodb.core.convert.MongoConversionContext;
|
||||
import org.springframework.data.mongodb.core.convert.MongoValueConverter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* {@link MongoValueConverter} to write {@link Address} into JSON through Jackson.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AddressJsonConverter implements MongoValueConverter<Address, String> {
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public Address read(String value, MongoConversionContext context) {
|
||||
|
||||
try {
|
||||
return mapper.readValue(value, Address.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalStateException("Cannot unmarshal Address JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String write(Address value, MongoConversionContext context) {
|
||||
try {
|
||||
return mapper.writeValueAsString(value);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalStateException("Cannot marshal Address into JSON", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2014-2021 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
|
||||
*
|
||||
* https://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.converters;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* Test configuration.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SpringBootApplication
|
||||
class ApplicationConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2014-2021 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
|
||||
*
|
||||
* https://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.converters;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.data.convert.ValueConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An entity to represent a customer.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Data
|
||||
@Document
|
||||
public class Customer {
|
||||
|
||||
private String id, firstname, lastname;
|
||||
|
||||
@ValueConverter(AddressJsonConverter.class) private Address primary;
|
||||
|
||||
@ValueConverter(AddressDocumentConverter.class) private Address secondary;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2014-2021 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
|
||||
*
|
||||
* https://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.converters;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import example.springdata.mongodb.util.MongoContainers;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link Customer} conversions.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Testcontainers
|
||||
@DataMongoTest
|
||||
class CustomerIntegrationTests {
|
||||
|
||||
@Container //
|
||||
private static MongoDBContainer mongoDBContainer = MongoContainers.getDefaultContainer();
|
||||
|
||||
@DynamicPropertySource
|
||||
static void setProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
|
||||
}
|
||||
|
||||
@Autowired MongoOperations operations;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
operations.remove(Customer.class).all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@link org.springframework.data.mongodb.core.convert.MongoValueConverter} to individual properties.
|
||||
* {@code primary} and {@code secondary} are configured with different converters of which the first one uses JSON
|
||||
* conversion and the second converter interacts directly with a MongoDB {@link Document}.
|
||||
*/
|
||||
@Test
|
||||
void appliesConverters() {
|
||||
|
||||
var primaryAddress = new Address(new Point(4.1, 5.6));
|
||||
primaryAddress.setStreet("308 Negra Arroyo Lane");
|
||||
primaryAddress.setZipCode("87104");
|
||||
|
||||
var secondaryAddress = new Address(new Point(6.1, 7.6));
|
||||
secondaryAddress.setStreet("3828 Piermont Drive");
|
||||
secondaryAddress.setZipCode("87111");
|
||||
|
||||
var customer = new Customer("Walter", "White");
|
||||
customer.setPrimary(primaryAddress);
|
||||
customer.setSecondary(secondaryAddress);
|
||||
|
||||
operations.insert(customer);
|
||||
|
||||
Document document = operations.findOne(new Query(), Document.class, "customer");
|
||||
|
||||
assertThat(document.get("primary"))
|
||||
.isEqualTo("{\"location\":{\"x\":4.1,\"y\":5.6},\"street\":\"308 Negra Arroyo Lane\",\"zipCode\":\"87104\"}");
|
||||
assertThat(document.get("secondary")).isEqualTo(
|
||||
new Document("x", secondaryAddress.getLocation().getX()).append("y", secondaryAddress.getLocation().getY()));
|
||||
|
||||
Customer loadedCustomer = operations.findOne(new Query(), Customer.class, "customer");
|
||||
|
||||
// Primary address marshalled as JSON
|
||||
assertThat(loadedCustomer.getPrimary()).isNotNull();
|
||||
assertThat(loadedCustomer.getPrimary().getStreet()).isEqualTo(primaryAddress.getStreet());
|
||||
assertThat(loadedCustomer.getPrimary().getZipCode()).isEqualTo(primaryAddress.getZipCode());
|
||||
assertThat(loadedCustomer.getPrimary().getLocation()).isEqualTo(primaryAddress.getLocation());
|
||||
|
||||
// Secondary address stores only location as the converter considers only points
|
||||
assertThat(loadedCustomer.getSecondary()).isNotNull();
|
||||
assertThat(loadedCustomer.getSecondary().getStreet()).isNull();
|
||||
assertThat(loadedCustomer.getSecondary().getLocation()).isEqualTo(secondaryAddress.getLocation());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Package showing converter usage with MongoDB entities.
|
||||
*/
|
||||
package example.springdata.mongodb.converters;
|
||||
Reference in New Issue
Block a user