1. Hibernate-OGM for MongoDB
2. Spring-Data MongoDB
1번은 hibernate-core, hibernate-search, hibernate-ogm 을 활용하여 검색 시스템을 만들어봐서, 이번에는 spring-data-mongodb 를 사용해보기로 했습니다.
예전에 spring-data-jpa 에서 repository 의 concrete class 를 안 만들고, 동적으로 생성해서 사용하는 방법을 보고, 와 정말 이렇게 되면 코딩량이 엄청 줄어들겠다 싶더군요...
그래서 이번에 spring-data-mongo 의 예제를 보고, 제 나름대로 다시 구성해 봤습니다.
spring-data 의 여러가지 모듈 사용법이 더 좋고, 생산성이 높다면, 앞으로는 이 것을 계속 사용하려고 합니다...
우선 spring-data-mongo 를 사용하기 위해 dependency에 다음을 추가합니다.
pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Spring framework --> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-core</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-context</artifactId> | |
</dependency> | |
<!-- Spring AOP --> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-aop</artifactId> | |
</dependency> | |
<!-- Spring Data MongoDB --> | |
<dependency> | |
<groupId>org.springframework.data</groupId> | |
<artifactId>spring-data-mongodb</artifactId> | |
</dependency> | |
<!-- QueryDSL for MongoDB --> | |
<dependency> | |
<groupId>com.mysema.querydsl</groupId> | |
<artifactId>querydsl-mongodb</artifactId> | |
</dependency> | |
<!-- QueryDSL apt --> | |
<dependency> | |
<groupId>com.mysema.querydsl</groupId> | |
<artifactId>querydsl-apt</artifactId> | |
<scope>provided</scope> | |
</dependency> |
다음으로 도메인 모델로 Album class 를 정의합니다.
Album.java
@Document 는 org.springframework.data.mongodb.core.mapping.Document 입니다.
이 어노테이션이 정의되면, MongoDB 의 Document 로 선언한 것입니다.
다음은 Album용 Repository를 정의합니다.
AlbumRepository.java
테스트용 환경 설정은 다음과 같이 합니다.
MongoConfiguration.java
주의할 점은 Repository 들을 실제 구현한 것이 아니라, Spring 이 동적으로 구현할 수 있도록 @EnableMongoRepositories 를 선언해 줘야 한다는 것입니다.
마지막으로 테스트 코드는 다음과 같습니다.
AlbumRepositoryIntegrationTest.java
를 구현하면 됩니다.
나머지 코드는 Spring-Data Mongo 의 예제에 있습니다. 그 예제는 xml 로 환경설정을 하고, 몇가지 제가 필요없는 코드를 제거했습니다.
시간나면 github에 따로 분리해서 올리도록 해보겠습니다...
Album.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Document | |
@Getter | |
@Setter | |
public class Album extends ValueObjectBase { | |
@Id | |
private ObjectId id; | |
private String title; | |
private String artist; | |
private List<Track> tracks = new ArrayList<Track>(); | |
public Album(String title, String artist) { | |
Guard.shouldNotBeEmpty(title, "title"); | |
Guard.shouldNotBeEmpty(artist, "artist"); | |
this.title = title; | |
this.artist = artist; | |
} | |
public void add(Track tract) { | |
this.tracks.add(tract); | |
} | |
@Override | |
public int hashCode() { | |
return HashTool.compute(id); | |
} | |
@Override | |
public Objects.ToStringHelper buildStringHelper() { | |
return super.buildStringHelper() | |
.add("id", id) | |
.add("title", title) | |
.add("artist", artist); | |
} | |
private static final long serialVersionUID = 958798390838794475L; | |
} |
이 어노테이션이 정의되면, MongoDB 의 Document 로 선언한 것입니다.
다음은 Album용 Repository를 정의합니다.
AlbumRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package kr.hconnect.mongo.test.music.model; | |
import org.bson.types.ObjectId; | |
import org.springframework.data.querydsl.QueryDslPredicateExecutor; | |
import org.springframework.data.repository.CrudRepository; | |
import org.springframework.stereotype.Repository; | |
import java.util.List; | |
/** | |
* Simple repositories interface to manage {@link Album} instances. | |
* | |
* @author 배성혁 sunghyouk.bae@gmail.com | |
* @since 13. 7. 20. 오후 4:16 | |
*/ | |
@Repository | |
public interface AlbumRepository extends CrudRepository<Album, ObjectId>, QueryDslPredicateExecutor<Album> { | |
List<Album> findByTracksName(String name); | |
List<Album> findByTracksNameLike(String name); | |
List<Album> findByTracksRatingGreaterThan(Stars rating); | |
} |
테스트용 환경 설정은 다음과 같이 합니다.
MongoConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package kr.hconnect.mongo.test.music; | |
import com.mongodb.Mongo; | |
import com.mongodb.MongoClient; | |
import kr.hconnect.mongo.test.music.model.AlbumRepository; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.data.mongodb.config.AbstractMongoConfiguration; | |
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; | |
import org.springframework.transaction.annotation.EnableTransactionManagement; | |
/** | |
* kr.hconnect.mongo.test.music.MongoConfiguration | |
* | |
* @author 배성혁 sunghyouk.bae@gmail.com | |
* @since 13. 7. 20. 오후 4:34 | |
*/ | |
@Configuration | |
@EnableTransactionManagement(proxyTargetClass = true) | |
/** 이게 있어야 Repository 의 Concrete Class를 생성해줍니다.*/ | |
@EnableMongoRepositories(basePackageClasses = { AlbumRepository.class }, repositoryImplementationPostfix = "Impl") | |
//@ComponentScan(basePackageClasses = { AlbumRepository.class }) | |
public class MongoConfiguration extends AbstractMongoConfiguration { | |
@Override | |
protected String getDatabaseName() { | |
return "musicDB"; | |
} | |
@Override | |
public Mongo mongo() throws Exception { | |
return new MongoClient("localhost"); | |
} | |
} |
주의할 점은 Repository 들을 실제 구현한 것이 아니라, Spring 이 동적으로 구현할 수 있도록 @EnableMongoRepositories 를 선언해 줘야 한다는 것입니다.
마지막으로 테스트 코드는 다음과 같습니다.
AlbumRepositoryIntegrationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package kr.hconnect.mongo.test.music.repositories; | |
import kr.hconnect.mongo.test.music.AbstractIntegrationTest; | |
import kr.hconnect.mongo.test.music.MongoConfiguration; | |
import kr.hconnect.mongo.test.music.model.Album; | |
import kr.hconnect.mongo.test.music.model.AlbumRepository; | |
import kr.hconnect.mongo.test.music.model.Stars; | |
import org.hamcrest.CoreMatchers; | |
import org.junit.Assert; | |
import org.junit.Before; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.test.context.ContextConfiguration; | |
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | |
import java.util.List; | |
import static org.fest.assertions.Assertions.assertThat; | |
/** | |
* kr.hconnect.mongo.test.music.repositories.AlbumRepositoryIntegrationTest | |
* | |
* @author 배성혁 sunghyouk.bae@gmail.com | |
* @since 13. 7. 20. 오후 4:53 | |
*/ | |
@RunWith(SpringJUnit4ClassRunner.class) | |
@ContextConfiguration(classes = { MongoConfiguration.class }) | |
public class AlbumRepositoryIntegrationTest extends AbstractIntegrationTest { | |
@Autowired | |
AlbumRepository repository; | |
@Before | |
public void purgeRepository() { | |
repository.deleteAll(); | |
super.setup(); | |
} | |
@Test | |
public void createAlbum() throws Exception { | |
repository.save(albums); | |
assertSingleGruxAlbum(repository.findOne(bigWhiskey.getId())); | |
} | |
@Test | |
public void findsAlbumByConcreteTrackName() throws Exception { | |
repository.save(albums); | |
assertSingleGruxAlbum(repository.findByTracksName("Grux")); | |
List<Album> albums = repository.findByTracksName("Foo"); | |
assertThat(albums.isEmpty()).isTrue(); | |
} | |
@Test | |
public void findsAllAlbumsByTrackNameLike() throws Exception { | |
repository.save(albums); | |
assertBothAlbums(repository.findByTracksNameLike("*it*")); | |
} | |
@Test | |
public void findsAlbumsByTrackRating() throws Exception { | |
bigWhiskey.getTracks().get(4).setRating(Stars.FOUR); | |
repository.save(albums); | |
assertSingleGruxAlbum(repository.findByTracksRatingGreaterThan(Stars.THREE)); | |
List<Album> albums = repository.findByTracksRatingGreaterThan(Stars.FOUR); | |
assertThat(albums.isEmpty()).isTrue(); | |
} | |
private void assertSingleGruxAlbum(List<Album> albums) { | |
Assert.assertThat(albums, CoreMatchers.is(CoreMatchers.notNullValue())); | |
Assert.assertThat(albums.size(), CoreMatchers.is(1)); | |
Assert.assertThat(albums.get(0), CoreMatchers.is(CoreMatchers.notNullValue(Album.class))); | |
assertSingleGruxAlbum(albums.get(0)); | |
} | |
} |
를 구현하면 됩니다.
나머지 코드는 Spring-Data Mongo 의 예제에 있습니다. 그 예제는 xml 로 환경설정을 하고, 몇가지 제가 필요없는 코드를 제거했습니다.
시간나면 github에 따로 분리해서 올리도록 해보겠습니다...
댓글 없음:
댓글 쓰기