Add example for unwrapping objects.

Closes #614.
This commit is contained in:
Christoph Strobl
2021-04-13 09:20:33 +02:00
committed by Mark Paluch
parent 3d0cad81a1
commit 19b3c92192
7 changed files with 348 additions and 0 deletions

View File

@@ -6,4 +6,5 @@ This project contains examples for:
* `EntityCallback` API usage for before convert/save interaction.
* Result projections for DTOs and interface types.
* Query metadata.
* Unwrapping entities into the parent document.

View File

@@ -0,0 +1,26 @@
/*
* Copyright 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.unwrapping;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Christoph Strobl
*/
@SpringBootApplication
public class ApplicationConfiguration {
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 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.unwrapping;
import java.util.Objects;
/**
* @author Christoph Strobl
*/
public class Email { // might as well be a record type in more recent java versions
private final String email;
public Email(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
@Override
public String toString() {
return email;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Email email1 = (Email) o;
return Objects.equals(email, email1.email);
}
@Override
public int hashCode() {
return Objects.hash(email);
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright 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.unwrapping;
import java.util.Objects;
import org.springframework.data.mongodb.core.mapping.Unwrapped;
import org.springframework.data.mongodb.core.mapping.Unwrapped.OnEmpty;
import org.springframework.lang.Nullable;
/**
* @author Christoph Strobl
*/
public class User {
@Nullable
private String id;
@Nullable
@Unwrapped(onEmpty = OnEmpty.USE_NULL)
private UserName userName;
/*
* The prefix allows to unwrap multiple properties of the same type assigning them a unique prefix.
* In this case the `Email.email` will be stored as `primary_email`.
*/
@Nullable
@Unwrapped(onEmpty = OnEmpty.USE_NULL, prefix = "primary_")
private Email email;
User() {
}
public User(String id, UserName userName, Email email) {
this.id = id;
this.userName = userName;
this.email = email;
}
User(String id, String userName, String email) {
this(id, new UserName(userName), new Email(email));
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public UserName getUserName() {
return userName;
}
public Email getEmail() {
return email;
}
public void setUserName(@Nullable UserName userName) {
this.userName = userName;
}
public void setEmail(@Nullable Email email) {
this.email = email;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id) &&
Objects.equals(userName, user.userName) &&
Objects.equals(email, user.email);
}
@Override
public int hashCode() {
return Objects.hash(id, userName, email);
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", userName=" + userName +
", email=" + email +
'}';
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 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.unwrapping;
import java.util.Objects;
/**
* @author Christoph Strobl
*/
public class UserName { // might as well be a record type in more recent java versions
private final String username;
public UserName(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserName userName = (UserName) o;
return Objects.equals(username, userName.username);
}
@Override
public int hashCode() {
return Objects.hash(username);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 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.unwrapping;
import org.springframework.data.repository.CrudRepository;
/**
* @author Christoph Strobl
*/
public interface UserRepository extends CrudRepository<User, String> {
/**
* Use the value type directly.
* This will unwrap the values into the target query object.
*/
User findByUserName(UserName userName);
/**
* Use one of the unwrapped properties.
* This will drill into the unwrapped using the value for the target query.
*/
User findByEmailEmail(String email);
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 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.unwrapping;
import static org.assertj.core.api.Assertions.*;
import java.util.Arrays;
import com.mongodb.client.model.Filters;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.test.context.junit.jupiter.SpringExtension;
/**
* @author Christoph Strobl
*/
@SpringBootTest
@ExtendWith(SpringExtension.class)
class UnwrappingIntegrationTests {
@Autowired UserRepository repository;
@Autowired MongoOperations operations;
User jane = new User("jane-01", new UserName("jane-villanueva"), new Email("jane@home.com"));
User rogelio = new User("rogelio-01", new UserName("rogelio-de-la-vega"), new Email("me@RogelioDeLaVega.com"));
@BeforeEach
void beforeEach() {
operations.dropCollection(User.class);
repository.saveAll(Arrays.asList(jane, rogelio));
}
@Test
void documentStructure() {
org.bson.Document stored = operations.execute(User.class, collection -> {
return collection.find(Filters.eq("_id", rogelio.getId())).first();
});
assertThat(stored).containsAllEntriesOf(new Document("_id", rogelio.getId())
.append("username", rogelio.getUserName().getUsername())
.append("primary_email", rogelio.getEmail().getEmail())
);
}
/**
* Query using the value type.
*/
@Test
void queryViaValueType() {
assertThat(repository.findByUserName(jane.getUserName())).isEqualTo(jane);
}
/**
* Query using a property of the embedded value type
*/
@Test
void queryViaPropertyOfValueType() {
assertThat(repository.findByEmailEmail(jane.getEmail().getEmail())).isEqualTo(jane);
}
}