Merge pull request #236 from alex-semenyuk/master
Introduction to Spring Data MongoDB (continue)
This commit is contained in:
commit
393c1eac14
|
@ -0,0 +1,12 @@
|
||||||
|
package org.baeldung.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
public @interface CascadeSave {
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,15 @@
|
||||||
package org.baeldung.config;
|
package org.baeldung.config;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.baeldung.converter.UserWriterConverter;
|
||||||
|
import org.baeldung.event.CascadeSaveMongoEventListener;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
|
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
|
||||||
|
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
|
@ -11,6 +19,8 @@ import com.mongodb.MongoClient;
|
||||||
@EnableMongoRepositories(basePackages = "org.baeldung.repository")
|
@EnableMongoRepositories(basePackages = "org.baeldung.repository")
|
||||||
public class MongoConfig extends AbstractMongoConfiguration {
|
public class MongoConfig extends AbstractMongoConfiguration {
|
||||||
|
|
||||||
|
private List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getDatabaseName() {
|
protected String getDatabaseName() {
|
||||||
return "test";
|
return "test";
|
||||||
|
@ -25,4 +35,15 @@ public class MongoConfig extends AbstractMongoConfiguration {
|
||||||
public String getMappingBasePackage() {
|
public String getMappingBasePackage() {
|
||||||
return "org.baeldung";
|
return "org.baeldung";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CascadeSaveMongoEventListener cascadingMongoEventListener() {
|
||||||
|
return new CascadeSaveMongoEventListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomConversions customConversions() {
|
||||||
|
converters.add(new UserWriterConverter());
|
||||||
|
return new CustomConversions(converters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.baeldung.converter;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.baeldung.model.User;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UserWriterConverter implements Converter<User, DBObject> {
|
||||||
|
@Override
|
||||||
|
public DBObject convert(User user) {
|
||||||
|
DBObject dbObject = new BasicDBObject();
|
||||||
|
dbObject.put("name", user.getName());
|
||||||
|
dbObject.put("age", user.getAge());
|
||||||
|
if (user.getEmailAddress() != null) {
|
||||||
|
DBObject emailDbObject = new BasicDBObject();
|
||||||
|
emailDbObject.put("value", user.getEmailAddress().getValue());
|
||||||
|
dbObject.put("email", emailDbObject);
|
||||||
|
}
|
||||||
|
dbObject.removeField("_class");
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package org.baeldung.event;
|
||||||
|
|
||||||
|
import org.baeldung.annotation.CascadeSave;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.mongodb.core.MongoOperations;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public class CascadeSaveMongoEventListener extends AbstractMongoEventListener<Object> {
|
||||||
|
@Autowired
|
||||||
|
private MongoOperations mongoOperations;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBeforeConvert(final Object source) {
|
||||||
|
ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
|
||||||
|
|
||||||
|
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
|
||||||
|
ReflectionUtils.makeAccessible(field);
|
||||||
|
|
||||||
|
if (field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)) {
|
||||||
|
final Object fieldValue = field.get(source);
|
||||||
|
|
||||||
|
if (fieldValue != null) {
|
||||||
|
FieldCallback callback = new FieldCallback();
|
||||||
|
|
||||||
|
ReflectionUtils.doWithFields(fieldValue.getClass(), callback);
|
||||||
|
|
||||||
|
mongoOperations.save(fieldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.baeldung.event;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
public class FieldCallback implements ReflectionUtils.FieldCallback {
|
||||||
|
private boolean idFound;
|
||||||
|
|
||||||
|
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
|
||||||
|
ReflectionUtils.makeAccessible(field);
|
||||||
|
|
||||||
|
if (field.isAnnotationPresent(Id.class)) {
|
||||||
|
idFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIdFound() {
|
||||||
|
return idFound;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.baeldung.model;
|
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
@Document
|
||||||
|
public class EmailAddress {
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
package org.baeldung.model;
|
package org.baeldung.model;
|
||||||
|
|
||||||
|
import org.baeldung.annotation.CascadeSave;
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mongodb.core.index.IndexDirection;
|
||||||
|
import org.springframework.data.mongodb.core.index.Indexed;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Field;
|
||||||
|
|
||||||
import com.mysema.query.annotations.QueryEntity;
|
import com.mysema.query.annotations.QueryEntity;
|
||||||
|
|
||||||
|
@ -11,9 +16,16 @@ public class User {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
|
@Indexed(direction = IndexDirection.ASCENDING)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private Integer age;
|
private Integer age;
|
||||||
|
|
||||||
|
@DBRef
|
||||||
|
@Field("email")
|
||||||
|
@CascadeSave
|
||||||
|
private EmailAddress emailAddress;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -37,4 +49,12 @@ public class User {
|
||||||
public void setAge(final Integer age) {
|
public void setAge(final Integer age) {
|
||||||
this.age = age;
|
this.age = age;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EmailAddress getEmailAddress() {
|
||||||
|
return emailAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmailAddress(EmailAddress emailAddress) {
|
||||||
|
this.emailAddress = emailAddress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||||
<constructor-arg name="mongo" ref="mongo"/>
|
<constructor-arg name="mongo" ref="mongo"/>
|
||||||
|
<constructor-arg ref="mongoConverter" />
|
||||||
<constructor-arg name="databaseName" value="test"/>
|
<constructor-arg name="databaseName" value="test"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
@ -24,7 +25,11 @@
|
||||||
|
|
||||||
<mongo:repositories base-package="org.baeldung.repository" mongo-template-ref="mongoTemplate"/>
|
<mongo:repositories base-package="org.baeldung.repository" mongo-template-ref="mongoTemplate"/>
|
||||||
|
|
||||||
<bean class="org.baeldung.event.BeforeConvertListener">
|
<bean class="org.baeldung.event.CascadeSaveMongoEventListener">
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<mongo:mapping-converter id="mongoConverter" base-package="org.baeldung.converter">
|
||||||
|
<mongo:custom-converters base-package="org.baeldung.converter"/>
|
||||||
|
</mongo:mapping-converter>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
|
@ -7,6 +7,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.baeldung.config.MongoConfig;
|
import org.baeldung.config.MongoConfig;
|
||||||
|
import org.baeldung.model.EmailAddress;
|
||||||
import org.baeldung.model.User;
|
import org.baeldung.model.User;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -31,11 +32,14 @@ public class DocumentQueryIntegrationTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void testSetup() {
|
public void testSetup() {
|
||||||
|
if (!mongoTemplate.collectionExists(User.class)) {
|
||||||
mongoTemplate.createCollection(User.class);
|
mongoTemplate.createCollection(User.class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
|
mongoTemplate.dropCollection(EmailAddress.class);
|
||||||
mongoTemplate.dropCollection(User.class);
|
mongoTemplate.dropCollection(User.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import static org.junit.Assert.assertThat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.baeldung.config.MongoConfig;
|
import org.baeldung.config.MongoConfig;
|
||||||
|
import org.baeldung.model.EmailAddress;
|
||||||
import org.baeldung.model.User;
|
import org.baeldung.model.User;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -15,7 +16,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
|
import org.springframework.data.mongodb.core.index.Index;
|
||||||
|
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
@ -30,8 +34,10 @@ public class MongoTemplateQueryIntegrationTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void testSetup() {
|
public void testSetup() {
|
||||||
|
if (!mongoTemplate.collectionExists(User.class)) {
|
||||||
mongoTemplate.createCollection(User.class);
|
mongoTemplate.createCollection(User.class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
|
@ -128,4 +134,42 @@ public class MongoTemplateQueryIntegrationTest {
|
||||||
List<User> users = mongoTemplate.find(query, User.class);
|
List<User> users = mongoTemplate.find(query, User.class);
|
||||||
assertThat(users.size(), is(3));
|
assertThat(users.size(), is(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenUserExistsWithIndexAddedFromMapping_whenCheckingIndex_thenIndexIsExisted() {
|
||||||
|
final User user = new User();
|
||||||
|
user.setName("Brendan");
|
||||||
|
EmailAddress emailAddress = new EmailAddress();
|
||||||
|
emailAddress.setValue("a@gmail.com");
|
||||||
|
user.setEmailAddress(emailAddress);
|
||||||
|
mongoTemplate.insert(user);
|
||||||
|
|
||||||
|
List<IndexInfo> indexInfos = mongoTemplate.indexOps("user").getIndexInfo();
|
||||||
|
|
||||||
|
assertThat(indexInfos.size(), is(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSavingUserWithEmailAddress_thenUserandEmailAddressSaved() {
|
||||||
|
final User user = new User();
|
||||||
|
user.setName("Brendan");
|
||||||
|
EmailAddress emailAddress = new EmailAddress();
|
||||||
|
emailAddress.setValue("b@gmail.com");
|
||||||
|
user.setEmailAddress(emailAddress);
|
||||||
|
mongoTemplate.insert(user);
|
||||||
|
|
||||||
|
assertThat(mongoTemplate.findOne(Query.query(Criteria.where("name").is("Brendan")), User.class).getEmailAddress().getValue(), is("b@gmail.com"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenUserExistsWithIndexAddedFromCode_whenCheckingIndex_thenIndexIsExisted() {
|
||||||
|
final User user = new User();
|
||||||
|
user.setName("Brendan");
|
||||||
|
mongoTemplate.indexOps(User.class).ensureIndex(new Index().on("name", Direction.ASC));
|
||||||
|
mongoTemplate.insert(user);
|
||||||
|
|
||||||
|
List<IndexInfo> indexInfos = mongoTemplate.indexOps("user").getIndexInfo();
|
||||||
|
|
||||||
|
assertThat(indexInfos.size(), is(2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,10 @@ public class BaseQueryIntegrationTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void testSetup() {
|
public void testSetup() {
|
||||||
|
if (!mongoOps.collectionExists(User.class)) {
|
||||||
mongoOps.createCollection(User.class);
|
mongoOps.createCollection(User.class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
|
|
|
@ -34,8 +34,10 @@ public class UserRepositoryIntegrationTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void testSetup() {
|
public void testSetup() {
|
||||||
|
if (!mongoOps.collectionExists(User.class)) {
|
||||||
mongoOps.createCollection(User.class);
|
mongoOps.createCollection(User.class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
|
@ -67,12 +69,11 @@ public class UserRepositoryIntegrationTest {
|
||||||
mongoOps.insert(user);
|
mongoOps.insert(user);
|
||||||
|
|
||||||
user = mongoOps.findOne(Query.query(Criteria.where("name").is("Jack")), User.class);
|
user = mongoOps.findOne(Query.query(Criteria.where("name").is("Jack")), User.class);
|
||||||
final String id = user.getId();
|
|
||||||
|
|
||||||
user.setName("Jim");
|
user.setName("Jim");
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
|
||||||
assertThat(mongoOps.findOne(Query.query(Criteria.where("id").is(id)), User.class).getName(), is("Jim"));
|
assertThat(mongoOps.findAll(User.class).size(), is(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -145,4 +146,5 @@ public class UserRepositoryIntegrationTest {
|
||||||
assertThat(users.size(), is(1));
|
assertThat(users.size(), is(1));
|
||||||
assertThat(page.getTotalPages(), is(2));
|
assertThat(page.getTotalPages(), is(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue