Skip to content

Commit 19b3c92

Browse files
christophstroblmp911de
authored andcommitted
Add example for unwrapping objects.
Closes #614.
1 parent 3d0cad8 commit 19b3c92

File tree

7 files changed

+348
-0
lines changed

7 files changed

+348
-0
lines changed

mongodb/example/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ This project contains examples for:
66
* `EntityCallback` API usage for before convert/save interaction.
77
* Result projections for DTOs and interface types.
88
* Query metadata.
9+
* Unwrapping entities into the parent document.
910

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.unwrapping;
17+
18+
import org.springframework.boot.autoconfigure.SpringBootApplication;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
@SpringBootApplication
24+
public class ApplicationConfiguration {
25+
26+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.unwrapping;
17+
18+
import java.util.Objects;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
public class Email { // might as well be a record type in more recent java versions
24+
25+
private final String email;
26+
27+
public Email(String email) {
28+
this.email = email;
29+
}
30+
31+
public String getEmail() {
32+
return email;
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return email;
38+
}
39+
40+
@Override
41+
public boolean equals(Object o) {
42+
if (this == o) return true;
43+
if (o == null || getClass() != o.getClass()) return false;
44+
Email email1 = (Email) o;
45+
return Objects.equals(email, email1.email);
46+
}
47+
48+
@Override
49+
public int hashCode() {
50+
return Objects.hash(email);
51+
}
52+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.unwrapping;
17+
18+
import java.util.Objects;
19+
20+
import org.springframework.data.mongodb.core.mapping.Unwrapped;
21+
import org.springframework.data.mongodb.core.mapping.Unwrapped.OnEmpty;
22+
import org.springframework.lang.Nullable;
23+
24+
/**
25+
* @author Christoph Strobl
26+
*/
27+
public class User {
28+
29+
@Nullable
30+
private String id;
31+
32+
@Nullable
33+
@Unwrapped(onEmpty = OnEmpty.USE_NULL)
34+
private UserName userName;
35+
36+
/*
37+
* The prefix allows to unwrap multiple properties of the same type assigning them a unique prefix.
38+
* In this case the `Email.email` will be stored as `primary_email`.
39+
*/
40+
@Nullable
41+
@Unwrapped(onEmpty = OnEmpty.USE_NULL, prefix = "primary_")
42+
private Email email;
43+
44+
User() {
45+
}
46+
47+
public User(String id, UserName userName, Email email) {
48+
49+
this.id = id;
50+
this.userName = userName;
51+
this.email = email;
52+
}
53+
54+
User(String id, String userName, String email) {
55+
this(id, new UserName(userName), new Email(email));
56+
}
57+
58+
public String getId() {
59+
return id;
60+
}
61+
62+
public void setId(String id) {
63+
this.id = id;
64+
}
65+
66+
public UserName getUserName() {
67+
return userName;
68+
}
69+
70+
public Email getEmail() {
71+
return email;
72+
}
73+
74+
public void setUserName(@Nullable UserName userName) {
75+
this.userName = userName;
76+
}
77+
78+
public void setEmail(@Nullable Email email) {
79+
this.email = email;
80+
}
81+
82+
@Override
83+
public boolean equals(Object o) {
84+
if (this == o) return true;
85+
if (o == null || getClass() != o.getClass()) return false;
86+
User user = (User) o;
87+
return Objects.equals(id, user.id) &&
88+
Objects.equals(userName, user.userName) &&
89+
Objects.equals(email, user.email);
90+
}
91+
92+
@Override
93+
public int hashCode() {
94+
return Objects.hash(id, userName, email);
95+
}
96+
97+
@Override
98+
public String toString() {
99+
return "User{" +
100+
"id='" + id + '\'' +
101+
", userName=" + userName +
102+
", email=" + email +
103+
'}';
104+
}
105+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.unwrapping;
17+
18+
import java.util.Objects;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
public class UserName { // might as well be a record type in more recent java versions
24+
25+
private final String username;
26+
27+
public UserName(String username) {
28+
this.username = username;
29+
}
30+
31+
public String getUsername() {
32+
return username;
33+
}
34+
35+
@Override
36+
public boolean equals(Object o) {
37+
if (this == o) return true;
38+
if (o == null || getClass() != o.getClass()) return false;
39+
UserName userName = (UserName) o;
40+
return Objects.equals(username, userName.username);
41+
}
42+
43+
@Override
44+
public int hashCode() {
45+
return Objects.hash(username);
46+
}
47+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.unwrapping;
17+
18+
import org.springframework.data.repository.CrudRepository;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
public interface UserRepository extends CrudRepository<User, String> {
24+
25+
/**
26+
* Use the value type directly.
27+
* This will unwrap the values into the target query object.
28+
*/
29+
User findByUserName(UserName userName);
30+
31+
/**
32+
* Use one of the unwrapped properties.
33+
* This will drill into the unwrapped using the value for the target query.
34+
*/
35+
User findByEmailEmail(String email);
36+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.unwrapping;
17+
18+
import static org.assertj.core.api.Assertions.*;
19+
20+
import java.util.Arrays;
21+
22+
import com.mongodb.client.model.Filters;
23+
import org.bson.Document;
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.api.extension.ExtendWith;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.boot.test.context.SpringBootTest;
29+
import org.springframework.data.mongodb.core.MongoOperations;
30+
import org.springframework.test.context.junit.jupiter.SpringExtension;
31+
32+
/**
33+
* @author Christoph Strobl
34+
*/
35+
@SpringBootTest
36+
@ExtendWith(SpringExtension.class)
37+
class UnwrappingIntegrationTests {
38+
39+
@Autowired UserRepository repository;
40+
@Autowired MongoOperations operations;
41+
42+
User jane = new User("jane-01", new UserName("jane-villanueva"), new Email("jane@home.com"));
43+
User rogelio = new User("rogelio-01", new UserName("rogelio-de-la-vega"), new Email("me@RogelioDeLaVega.com"));
44+
45+
@BeforeEach
46+
void beforeEach() {
47+
48+
operations.dropCollection(User.class);
49+
repository.saveAll(Arrays.asList(jane, rogelio));
50+
}
51+
52+
@Test
53+
void documentStructure() {
54+
55+
org.bson.Document stored = operations.execute(User.class, collection -> {
56+
return collection.find(Filters.eq("_id", rogelio.getId())).first();
57+
});
58+
59+
assertThat(stored).containsAllEntriesOf(new Document("_id", rogelio.getId())
60+
.append("username", rogelio.getUserName().getUsername())
61+
.append("primary_email", rogelio.getEmail().getEmail())
62+
);
63+
}
64+
65+
66+
/**
67+
* Query using the value type.
68+
*/
69+
@Test
70+
void queryViaValueType() {
71+
assertThat(repository.findByUserName(jane.getUserName())).isEqualTo(jane);
72+
}
73+
74+
/**
75+
* Query using a property of the embedded value type
76+
*/
77+
@Test
78+
void queryViaPropertyOfValueType() {
79+
assertThat(repository.findByEmailEmail(jane.getEmail().getEmail())).isEqualTo(jane);
80+
}
81+
}

0 commit comments

Comments
 (0)