1. 程式人生 > >Spring Boot(十一):Spring Boot中MongoDB的使用

Spring Boot(十一):Spring Boot中MongoDB的使用

Spring Boot(十一):Spring Boot中MongoDB的使用

mongodb是最早熱門非關係資料庫的之一,使用也比較普遍,一般會用做離線資料分析來使用,放到內網的居多。由於很多公司使用了雲服務,伺服器預設都開放了外網地址,導致前一陣子大批 MongoDB 因配置漏洞被攻擊,資料被刪,引起了人們的注意,感興趣的可以看看這篇文章:場屠戮MongoDB的盛宴反思:超33000個數據庫遭遇入侵勒索,同時也說明了很多公司生產中大量使用mongodb。

一、MongoDB簡介

MongoDB(來自於英文單詞“Humongous”,中文含義為“龐大”)是可以應用於各種規模的企業、各個行業以及各類應用程式的開源資料庫。基於分散式檔案儲存的資料庫。由C++語言編寫。旨在為WEB應用提供可擴充套件的高效能資料儲存解決方案。MongoDB是一個高效能,開源,無模式的文件型資料庫,是當前NoSql資料庫中比較熱門的一種。

MongoDB是一個介於關係資料庫和非關係資料庫之間的產品,是非關係資料庫當中功能最豐富,最像關係資料庫的。他支援的資料結構非常鬆散,是類似json的bjson格式,因此可以儲存比較複雜的資料型別。Mongo最大的特點是他支援的查詢語言非常強大,其語法有點類似於面向物件的查詢語言,幾乎可以實現類似關係資料庫單表查詢的絕大部分功能,而且還支援對資料建立索引。

傳統的關係資料庫一般由資料庫(database)、表(table)、記錄(record)三個層次概念組成,MongoDB是由資料庫(database)、集合(collection)、文件物件(document)三個層次組成。MongoDB對於關係型資料庫裡的表,但是集合中沒有列、行和關係概念,這體現了模式自由的特點。

MongoDB中的一條記錄就是一個文件,是一個數據結構,由欄位和值對組成。MongoDB文件與JSON物件類似。欄位的值有可能包括其它文件、陣列以及文件陣列。MongoDB支援OS X、Linux及Windows等作業系統,並提供了Python,PHP,Ruby,Java及C++語言的驅動程式,社群中也提供了對Erlang及.NET等平臺的驅動程式。

MongoDB的適合對大量或者無固定格式的資料進行儲存,比如:日誌、快取等。對事物支援較弱,不適用複雜的多文件(多表)的級聯查詢。文中演示mongodb版本為3.4。

二、MongoDB的增刪改查

Spring Boot對各種流行的資料來源都進行了封裝,當然也包括了mongodb,下面給大家介紹如何在spring boot中使用mongodb:

1,pom包配置

pom包裡面新增spring-boot-starter-data-mongodb包引用

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

2,在application.properties中新增配置

spring.data.mongodb.uri=mongodb://name:[email protected]:27017/test

多個IP叢集可以採用以下配置:

spring.data.mongodb.uri=mongodb://user:[email protected]:port1,ip2:port2/database

3,建立資料實體

public class UserEntity implements Serializable {
        private static final long serialVersionUID = -3258839839160856613L;
        private Long id;
        private String userName;
        private String passWord;

      //getter、setter省略
}

4,建立實體dao的增刪改查操作

dao層實現了UserEntity物件的增刪改查

@Component
public class UserDaoImpl implements UserDao {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 建立物件
     * @param user
     */
    @Override
    public void saveUser(UserEntity user) {
        mongoTemplate.save(user);
    }

    /**
     * 根據使用者名稱查詢物件
     * @param userName
     * @return
     */
    @Override
    public UserEntity findUserByUserName(String userName) {
        Query query=new Query(Criteria.where("userName").is(userName));
        UserEntity user =  mongoTemplate.findOne(query , UserEntity.class);
        return user;
    }

    /**
     * 更新物件
     * @param user
     */
    @Override
    public void updateUser(UserEntity user) {
        Query query=new Query(Criteria.where("id").is(user.getId()));
        Update update= new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord());
        //更新查詢返回結果集的第一條
        mongoTemplate.updateFirst(query,update,UserEntity.class);
        //更新查詢返回結果集的所有
        // mongoTemplate.updateMulti(query,update,UserEntity.class);
    }

    /**
     * 刪除物件
     * @param id
     */
    @Override
    public void deleteUserById(Long id) {
        Query query=new Query(Criteria.where("id").is(id));
        mongoTemplate.remove(query,UserEntity.class);
    }
}

5,開發對應的測試方法

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {

    @Autowired
    private UserDao userDao;

    @Test
    public void testSaveUser() throws Exception {
        UserEntity user=new UserEntity();
        user.setId(2l);
        user.setUserName("小明");
        user.setPassWord("fffooo123");
        userDao.saveUser(user);
    }

    @Test
    public void findUserByUserName(){
       UserEntity user= userDao.findUserByUserName("小明");
       System.out.println("user is "+user);
    }

    @Test
    public void updateUser(){
        UserEntity user=new UserEntity();
        user.setId(2l);
        user.setUserName("天空");
        user.setPassWord("fffxxxx");
        userDao.updateUser(user);
    }

    @Test
    public void deleteUserById(){
        userDao.deleteUserById(1l);
    }

}

6,檢視驗證結果

可以使用工具mongoVUE工具來連線後直接圖形化展示檢視,也可以登入伺服器用命令來檢視

(1)登入mongos

bin/mongo -host localhost -port 20000

(2)切換到test庫

use test

(3)查詢userEntity集合資料

db.userEntity.find()

根據3查詢的結果來觀察測試用例的執行是否正確。

到此springboot對應mongodb的增刪改查功能已經全部實現。

二、多資料來源mongodb的使用

在多mongodb資料來源的情況下,我們換種更優雅的方式來實現

1,pom包配置

新增lombok和spring-boot-autoconfigure包引用

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>RELEASE</version>
</dependency>
  • Lombok - 是一個可以通過簡單的註解形式來幫助我們簡化消除一些必須有但顯得很臃腫的Java程式碼的工具,通過使用對應的註解,可以在編譯原始碼的時候生成對應的方法。簡單試了以下這個工具還挺好玩的,加上註解我們就不用手動寫 getter\setter、構建方式類似的程式碼了。

  • spring-boot-autoconfigure - 就是spring boot的自動化配置

2,配置檔案使用YAML的形式新增兩條資料來源,如下:

mongodb:
  primary:
    host: 192.168.9.60
    port: 20000
    database: test
  secondary:
    host: 192.168.9.60
    port: 20000
    database: test1

3,配置兩個庫的資料來源

封裝讀取以mongodb開頭的兩個配置檔案

@Data
@ConfigurationProperties(prefix = "mongodb")
public class MultipleMongoProperties {

    private MongoProperties primary = new MongoProperties();
    private MongoProperties secondary = new MongoProperties();
}

配置不同包路徑下使用不同的資料來源

第一個庫的封裝

@Configuration
@EnableMongoRepositories(basePackages = "com.neo.model.repository.primary",
        mongoTemplateRef = PrimaryMongoConfig.MONGO_TEMPLATE)
public class PrimaryMongoConfig {

    protected static final String MONGO_TEMPLATE = "primaryMongoTemplate";
}

第二個庫的封裝

@Configuration
@EnableMongoRepositories(basePackages = "com.neo.model.repository.secondary",
        mongoTemplateRef = SecondaryMongoConfig.MONGO_TEMPLATE)
public class SecondaryMongoConfig {

    protected static final String MONGO_TEMPLATE = "secondaryMongoTemplate";
}

讀取對應的配置資訊並且構造對應的MongoTemplate

@Configuration
public class MultipleMongoConfig {

    @Autowired
    private MultipleMongoProperties mongoProperties;

    @Primary
    @Bean(name = PrimaryMongoConfig.MONGO_TEMPLATE)
    public MongoTemplate primaryMongoTemplate() throws Exception {
        return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
    }

    @Bean
    @Qualifier(SecondaryMongoConfig.MONGO_TEMPLATE)
    public MongoTemplate secondaryMongoTemplate() throws Exception {
        return new MongoTemplate(secondaryFactory(this.mongoProperties.getSecondary()));
    }

    @Bean
    @Primary
    public MongoDbFactory primaryFactory(MongoProperties mongo) throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(mongo.getHost(), mongo.getPort()),
                mongo.getDatabase());
    }

    @Bean
    public MongoDbFactory secondaryFactory(MongoProperties mongo) throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(mongo.getHost(), mongo.getPort()),
                mongo.getDatabase());
    }
}

兩個庫的配置資訊已經完成。

4,建立兩個庫分別對應的物件和Repository

藉助lombok來構建物件

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "first_mongo")
public class PrimaryMongoObject {

    @Id
    private String id;

    private String value;

    @Override
    public String toString() {
        return "PrimaryMongoObject{" + "id='" + id + '\'' + ", value='" + value + '\''
                + '}';
    }
}

對應的Repository

public interface PrimaryRepository extends MongoRepository<PrimaryMongoObject, String> {
}

繼承了 MongoRepository 會預設實現很多基本的增刪改查,省了很多自己寫dao層的程式碼

Secondary和上面的程式碼類似就不貼出來了

三、測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class MuliDatabaseTest {

    @Autowired
    private PrimaryRepository primaryRepository;

    @Autowired
    private SecondaryRepository secondaryRepository;

    @Test
    public void TestSave() {

        System.out.println("************************************************************");
        System.out.println("測試開始");
        System.out.println("************************************************************");

        this.primaryRepository
                .save(new PrimaryMongoObject(null, "第一個庫的物件"));

        this.secondaryRepository
                .save(new SecondaryMongoObject(null, "第二個庫的物件"));

        List<PrimaryMongoObject> primaries = this.primaryRepository.findAll();
        for (PrimaryMongoObject primary : primaries) {
            System.out.println(primary.toString());
        }

        List<SecondaryMongoObject> secondaries = this.secondaryRepository.findAll();

        for (SecondaryMongoObject secondary : secondaries) {
            System.out.println(secondary.toString());
        }

        System.out.println("************************************************************");
        System.out.println("測試完成");
        System.out.println("************************************************************");
    }

}