配置嵌入式 MongoDB 的最简单方法

Posted

技术标签:

【中文标题】配置嵌入式 MongoDB 的最简单方法【英文标题】:The easiest way to configure Embedded MongoDB 【发布时间】:2018-02-07 22:06:36 【问题描述】:

我想知道,是否有任何示例如何正确配置嵌入式MongoDBSpring Boot

例如,这是我配置 H2 嵌入式数据库的方式:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.jndi.JndiObjectFactoryBean;

import javax.sql.DataSource;


@Configuration
@PropertySource("configs/datasource.properties")
public class DataSourceConfig 

    @Bean
    @Profile("test")
    public DataSource testDataSource() 
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
    

这很好用,但是有一个问题。此方法不提供 MongoDB 配置。

有什么解决方法吗?

更新 1:

[ERROR] 未能执行目标 org.springframework.boot:spring-boot-maven-plugin:1.5.6.RELEASE:run 项目 XXX 上的 (default-cli): 发生异常时 跑步。 null:InvocationTargetException:创建 bean 时出错 在类路径资源中定义的名称“mongoTemplate” [com/reborn/XXX/config/DataSourceConfig .class]:豆 通过工厂方法实例化失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:失败 实例化 [org.springframework k.data.mongodb.core.MongoTemplate]: 工厂方法 'mongoTemplate' 抛出异常;嵌套异常是 java.lang.NoClassDefFoundError: de/flapdoodle/embed/mongo/distribu 化/IFeatureAwareVersion: de.flapdoodle.embed.mongo.distribution.IFeatureAwareVersion -> [帮助 1]

更新 2:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.reborn</groupId>
    <artifactId>xxx</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>xxx</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repositories -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cz.jirutka.spring</groupId>
            <artifactId>embedmongo-spring</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

数据源配置:

package com.reborn.xxx.config;

import com.mongodb.MongoClient;
import cz.jirutka.spring.embedmongo.EmbeddedMongoFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.io.IOException;

@Configuration
public class DataSourceConfig 

    @Bean
    public MongoTemplate mongoTemplate() throws IOException 
        EmbeddedMongoFactoryBean mongo = new EmbeddedMongoFactoryBean();
        mongo.setBindIp("localhost");
        MongoClient mongoClient = mongo.getObject();
        MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, "abcd");
        return mongoTemplate;
    


更新 3:

[错误] 无法执行目标 org.springframework.boot:spring-boot-maven-plugin:1.5.6.RELEASE:run (default-cli) on project starbucks-finder: 发生异常时 跑步。 null:InvocationTargetException:在类路径资源 [com/reborn/xxx/config/DataSourceConfig 中定义的名称为“mongoTemplate”的 bean 创建时出错 .class]:通过工厂方法实例化 Bean 失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframewor k.data.mongodb.core.MongoTemplate]:工厂方法'mongoTemplate'抛出异常;嵌套异常为 java.lang.IllegalArgumentException:此版本不支持 32 位:生产:Windows:B32 -> [帮助 1]

【问题讨论】:

How do you configure Embedded MongDB for integration testing in a Spring Boot application?的可能重复 【参考方案1】:

对于带有 JUnit5 的 Spring Boot 2.2.x

pom.xml

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>

测试类(可以设置 MongoDB 版本)

@ExtendWith(SpringExtension.class)
@DataMongoTest
class ModelRepoIntegrationTest 

    private static final String IP = "localhost";
    private static final int PORT = 28017; // <- set MongoDB port

    @TestConfiguration
    @Import(ModelRepo.class) // <- set the tested repository
    // @ComponentScan("com.example.repo") <- or package for several repositories
    static class Config 
        @Bean
        public IMongodConfig embeddedMongoConfiguration() throws IOException 
            return new MongodConfigBuilder()
                    .version(Version.V4_0_2) // <- set MongoDB version
                    .net(new Net(IP, PORT, Network.localhostIsIPv6()))
                    .build();
        
    

    @Autowired private ModelRepo repo; // <- tested repository
    @Autowired private MongoTemplate mongo; 

    @BeforeEach
    void setUp()  // clean db (slower) or collection (faster) before each test
        // mongo.getDb().drop();
        mongo.remove(new Query(), Model.class); 
    

    @Test
    void create() 
        Model model = new Model() // <- tested entity
                          .setId(UUID.randomUUID())
                          .setNum(1)
                          .setText("text");
        Model actual = repo.create(model); // <- tested method of the repository
        List<Model> models = mongo.findAll(Model.class);
        assertThat(models).hasSize(1);
        Model expected = models.get(0);
        assertThat(actual).isEqualToComparingFieldByField(expected);
    

【讨论】:

【参考方案2】:

它将自动配置相关依赖项的新版本或可兼容版本

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


<dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <version>1.50.5</version>
        </dependency>
        <dependency>
            <groupId>cz.jirutka.spring</groupId>
            <artifactId>embedmongo-spring</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


        @Repository
public interface yourRepository extends MongoRepository<Class Type, String> 


【讨论】:

【参考方案3】:

flapdoodle embedded MongoDB 可以与 Spring Boot 集成。

声明对fladdoodle的依赖:

<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.mongo</artifactId>
    <version>2.0.0</version>
</dependency>

声明对库的依赖,为 fladdoodle 的嵌入式 MongoDB 提供 Spring 工厂 bean:

<dependency>
    <groupId>cz.jirutka.spring</groupId>
    <artifactId>embedmongo-spring</artifactId>
    <version>1.3.1</version>
</dependency>

大概你已经声明了对spring-boot-starter-data-mongodb的依赖:

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

现在,只需配置一个指向嵌入式 MongoDB 实例的 MongoTemplate

@Bean
public MongoTemplate mongoTemplate() throws IOException 
    EmbeddedMongoFactoryBean mongo = new EmbeddedMongoFactoryBean();
    mongo.setBindIp("localhost");
    MongoClient mongoClient = mongo.getObject();
    MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, "test_or_whatever_you_want_to_call_this_db");
    return mongoTemplate;

【讨论】:

项目启动存在一些问题。查看主题更新。 @Reborn 你是说你更新了原来的问题来描述“项目启动的一些问题”?如果是这样,我看不到任何描述此问题的详细信息。也许你可以provide a MCVE? 此异常:java.lang.NoClassDefFoundError: de/flapdoodle/embed/mongo/distribution/IFeatureAwareVersion 意味着(1)您尚未添加 de.flapdoodle.embed.mongo 依赖项或(2)您在添加 de.flapdoodle.embed.mongo 依赖项后尚未运行 mvn install 并且在运行 mvn spring-boot:run 之前。您能否更新您的问题以包括(1)您更新的 pom.xml 和(2)您的 MongoTemplate 声明。 主题已更新。 start.spring.io 除了cz.jirutka.spring 之外,已经添加了您告诉的大部分依赖项。我已经多次完成mvn clean install 以确保一切正常,但如您所见,仍然存在问题。 您没有为 de.flapdoodle.embed.mongo 依赖项指定版本,这意味着对于 Spring Boot 1.5.6.RELEASE,您使用的是 v1.50.5。我使用 v2.0.0 验证了我的帖子中的实现(即我的答案中明确引用的版本)。但是,de.flapdoodle.embed.mongo 的 v1.50.5 还包括 IFeatureAwareVersion,所以应该没问题。 AFAICT,您的设置有效,您可以在 IDE 中浏览到 IFeatureAwareVersion 吗?您是否检查过此文件:de.flapdoodle.embed.mongo-1.50.5.jar 是否存在于您的本地 Maven 存储库中,并且它包含 IFeatureAwareVersion

以上是关于配置嵌入式 MongoDB 的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章

从 cargo-maven2-plugin 以嵌入式模式启动 tomcat 的最简单方法是啥?

嵌入 Python 时共享数组的最简单方法

将 pcap 转换为 JSON 的最简单方法

mongodb - 按顺序计算缺失索引的最有效方法

在视图中访问 Phalcon 配置值的最简单方法是啥?

带二级目录的Nginx配置------目前找到的最简单的方法