Spring Boot(12)——使用MongoDB

使用MongoDB

需要在Spring Boot應用中使用MongoDB,可以在pom.xml中添加spring-boot-starter-data-mongodb依賴,這樣Spring Boot會自動配置MongoDB的相關bean,比如MongoClient、MongoTemplate等,可以參考Spring Data MongoDB的自動配置類org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration的API文檔或源碼。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

默認配置的MongoDB連接對應的主機是localhost,端口號是標準端口號27017,database是test。可以通過spring.data.mongodb打頭的配置屬性進行配置,對應的屬性將綁定到org.springframework.boot.autoconfigure.mongo.MongoProperties對象,下面的代碼重新配置了主機、端口號和database。更多配置信息可以參考MongoProperties的API文檔或源代碼。

spring.data.mongodb.host=10.192.48.170
spring.data.mongodb.port=27017
spring.data.mongodb.database=test_db

之後就可以直接通過MongoTemplate進行MongoDB的操作了。下面的代碼中定義了一個User類,其userId屬性對應MongoDB的user這個document的id屬性,username屬性對應於MongoDB的user這個document的user_name屬性。然後在測試類中,new了一個User對象,通過MongoTemplate對象把它存入到了MongoDB中。

@Document
@Data
public class User {

    @Id
    private Long userId;
    private String name;
    @Field("user_name")
    private String username;
    
}

@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {

    @Autowired
    private MongoTemplate mongoTemplate;
    
    @Test
    public void testSave() {
        User user = new User();
        user.setUserId(2L);
        user.setName("張三");
        user.setUsername("zhangsan");
        this.mongoTemplate.save(user);
    }
    
}

也可以定義Spring Data Repository,通過Repository對MongoDB進行訪問。定義的Repository,Spring Boot將自動對其進行掃描,由org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration定義,掃描路徑是Spring Boot啓動類所在的包。有需要也可以手動加上@EnableMongoRepositories以指定需要掃描的路徑。下面的代碼定義了一個UserRepository,其繼承自標準的MongoRepository,同時又按照Spring Data的規範定義了一個findByName方法。

public interface UserRepository extends MongoRepository<User, Long> {

    List<User> findByName(String name);
    
}

之後可以直接在需要的地方注入UserRepository,通過UserRepository訪問MongoDB,下面的代碼中就分別利用注入的UserRepository進行了User對象的新增和查詢操作。

@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {

    @Autowired
    private UserRepository userRepository;
    
    @Test
    public void testSave() {
        User user = new User();
        user.setUserId(3L);
        user.setName("張三");
        user.setUsername("zhangsan");
        this.userRepository.save(user);
    }
    
    @Test
    public void testFindByName() {
        List<User> users = this.userRepository.findByName("張三");
        Assert.assertNotNull(users);
        Assert.assertEquals("張三", users.get(0).getName());
    }
    
}

本文旨在描述在Spring Boot應用中如何使用MongoDB,所以對Spring Data MongoDB的內容沒有講解太多。

基於Reactive編程

如果期望基於Reactive編程則可以引入spring-boot-starter-data-mongodb-reactive依賴。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>

引入該依賴後Spring Boot將自動配置一個ReactiveMongoTemplate,它默認使用Reactor實現進行Reactive編程。我們可以直接在應用中注入ReactiveMongoTemplate實例,通過它進行相關Reactive操作。下面的代碼展示了通過ReactiveMongoTemplate進行User對象的保存操作。

@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {

    @Autowired
    private ReactiveMongoTemplate reactiveMongoTemplate;
    
    @Test
    public void testReactive() {
        User user = new User();
        user.setUserId(4L);
        user.setName("李四");
        user.setUsername("lisi");
        Mono<User> mono = this.reactiveMongoTemplate.save(user);
        mono.block();
    }
    
    
}

Repository中的相關操作也是可以基於Reactive的,這需要我們定義的Repository繼承自下面的四個接口之一,其中前面兩個是基於Reactor實現,後面兩個是基於RxJava2實現。以SortingRepository結尾的Repository都繼承自對應的CrudRepository。

  • ReactiveCrudRepository
  • ReactiveSortingRepository
  • RxJava2CrudRepository
  • RxJava2SortingRepository

添加了spring-boot-starter-data-mongodb-reactive依賴後,會自動添加Reactor依賴,所以可以直接使用ReactiveCrudRepository和ReactiveSortingRepository。下面的代碼中定義的ReactiveUserRepository就是基於ReactiveSortingRepository實現的,同時擴展了一個查詢操作findByUsername,其返回結果是Reactor實現的Flux。

public interface ReactiveUserRepository extends ReactiveSortingRepository<User, Long> {

    Flux<User> findByUsername(String username);
    
}

上面定義的ReactiveUserRepository也會被自動掃描到,並被註冊爲Spring bean,在程序中可以直接注入ReactiveUserRepository對象進行使用,比如下面代碼這樣。

@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {

    @Autowired
    private ReactiveUserRepository reactiveUserRepository;
    
    @Test
    public void testReactiveUserRepository() throws Exception {
        User user = new User();
        user.setUserId(System.currentTimeMillis());
        user.setName("李四");
        user.setUsername("lisi");
        Mono<User> mono = this.reactiveUserRepository.save(user);
        mono.subscribe(u -> System.out.println("saved success : " + u));
        
        //get users by username
        Flux<User> flux = this.reactiveUserRepository.findByUsername("lisi");
        flux.subscribe(System.out::println);
        TimeUnit.SECONDS.sleep(1);
    }
    
}

如果需要使用RxJava2CrudRepository和RxJava2SortingRepository,則需要引入RxJava2的依賴。

<dependency>
    <groupId>io.reactivex.rxjava2</groupId>
    <artifactId>rxjava</artifactId>
</dependency>

之後可以像使用ReactiveCrudRepository一樣使用它們。下面的代碼定義了一個基於RxJava2的Repository,同時擴展了一個findByUsername查詢,返回類型是RxJava2實現的Flowable。

public interface RxJava2UserRepository extends RxJava2SortingRepository<User, Long> {

    Flowable<User> findByUsername(String username);
    
}

它也可以直接被掃描和定義爲一個Spring bean,所以也可以直接在程序中進行注入。

@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {
    
    @Autowired
    private RxJava2UserRepository rxJava2UserRepository;
    
    @Test
    public void testRxJava2UserRepository() throws Exception {
        User user = new User();
        user.setUserId(System.currentTimeMillis());
        user.setName("李四");
        user.setUsername("lisi");
        Single<User> single = this.rxJava2UserRepository.save(user);
        System.out.println("saved success : " + single.blockingGet());
        
        //get users by username
        Flowable<User> flowable = this.rxJava2UserRepository.findByUsername("lisi");
        flowable.subscribe(System.out::println);
        TimeUnit.SECONDS.sleep(1);
    }
    
}

(注:本文是基於Spring Boot 2.0.3所寫)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章