使用自定义集合名称的Spring Data MongoDB Repository

7
我将使用Spring Data for MongoDB,并需要在运行时配置集合。
我的存储库定义如下:
@Repository
public interface EventDataRepository extends MongoRepository<EventData, String> {
}

我尝试了这个愚蠢的例子:

@Document(collection = "${mongo.event.collection}")
public class EventData implements Serializable {

但是mongo.event.collection没有像@Value注释一样解析为名称。
稍作调试和搜索之后,我尝试了以下代码: @Document(collection = "#{${mongo.event.collection}}")
这将产生一个异常:
Caused by: org.springframework.expression.spel.SpelParseException: EL1041E:(pos 1): After parsing a valid expression, there is still more data in the expression: 'lcurly({)'
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:129)
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:60)
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:32)
    at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpressions(TemplateAwareExpressionParser.java:154)
    at org.springframework.expression.common.TemplateAwareExpressionParser.parseTemplate(TemplateAwareExpressionParser.java:85)

也许我只是不知道如何使用SPel从Spring的属性配置器中访问值。
当我在代码中单步执行时,我看到有一种指定集合名称甚至表达式的方式,但我不确定应该使用哪个注释来实现此目的或如何做到这一点。
谢谢。 -AP_

也许这就是你的问题所在?https://jira.spring.io/browse/DATAMONGO-1043 ... 你正在使用哪个版本的spring-data-mongodb? - Benjamin M
可能是因为我使用的是1.7.0-RELEASE版本,但是你提到的问题涉及到多次调用之间查询表达式的处理。不过,你提醒了我必须使用正确的SPEL表达式,所以我进行了更改。请查看更新后的问题。 - Alex Paransky
4个回答

6
您可以通过使用SPeL来解决这个问题:
@Document(collection = "#{environment.getProperty('mongo.event.collection')}")
public class EventData implements Serializable {
    ...
}

更新 Spring 5.x:

自 Spring 5.x 开始,您需要在 environment 前面加上一个额外的 @ 符号:

@Document(collection = "#{@environment.getProperty('mongo.event.collection')}")
public class EventData implements Serializable {
    ...
}

文档:

这些文档与it技术有关,涉及Spring框架中的表达式和bean定义。它们将帮助您更好地理解如何在Spring应用程序中使用表达式和访问属性。

1
你真是个救星。我知道评论不应该用来表示感谢,但这解决了我很多问题。您能否友好地包含Spring文档的参考资料? - Missaka Iddamalgoda
1
我添加了一些文档,描述了示例代码中使用的所有部件。这对你有帮助吗? - Oliver Koch
1
对于那些在Spring文档中遇到章节链接无法工作的人,请参考第4章。 - Missaka Iddamalgoda
1
我将章节编号添加到了href标签中。 - Oliver Koch

5

最终,这里提供了一个解决方案。我猜我真的不知道如何使用SPeL表达式从Spring Properties Configurer中访问数据。

在我的@Configuration类中:

@Value("${mongo.event.collection}")
private String
    mongoEventCollectionName;

@Bean
public String mongoEventCollectionName() {
    return
        mongoEventCollectionName;
}

在我的文档中:

@Document(collection = "#{mongoEventCollectionName}")

这个代码似乎可以正常工作并且正确获取在我.properties文件中配置的名称,然而,我仍然不确定为什么我不能像在@Value注释中一样使用$来访问该值。


这个回答在某些方面对我有帮助,但是我仍然遇到一个错误:“空值上找不到属性或字段'mongoEventCollectionName'”。向bean注入似乎没有问题,但是向@Document注入却存在问题。 - jmmut
1
我通过这个答案使它工作了:将ApplicationContext设置为MongoMappingContext。 - jmmut

3
请定义您的实体类,例如:
@Document(collection = "${EventDataRepository.getCollectionName()}")
public class EventData implements Serializable {

定义一个自定义的仓库接口,并包含 getter 和 setter 方法以处理“collectionName”

public interface EventDataRepositoryCustom {

    String getCollectionName();

    void setCollectionName(String collectionName);
}

提供实现自定义存储库的“collectionName”实现类。
public class EventDataRepositoryImpl implements EventDataRepositoryCustom{

    private static String collectionName = "myCollection";

    @Override
    public String getCollectionName() {
        return collectionName;
    }

    @Override
    public void setCollectionName(String collectionName) {
        this.collectionName = collectionName;
    }
}

EventDataRepositoryImpl添加到您的存储库接口的扩展列表中,代码如下:
@Repository
public interface EventDataRepository extends MongoRepository<EventData, String>, EventDataRepositoryImpl  {
}

现在,在您使用 MongoRepository 的 Service 类中设置集合名称,它会像这样:

@Autowired
EventDataRepository  repository ;

repository.setCollectionName("collectionName");

0
实体类
@Document    // remove the parameters from here


public class EscalationCase 
{

}

配置类

public class MongoDBConfiguration {

    private final Logger logger = LoggerFactory.getLogger(MongoDBConfiguration.class);

    @Value("${sfdc.mongodb.collection}") //taking collection name from properties file 
    private String collectionName;

    @Bean

    public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoMappingContext context) {

        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), context);
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
        if (!mongoTemplate.collectionExists(collectionName)) {
            mongoTemplate.createCollection(collectionName);  // adding the collection name here
        }
        return mongoTemplate;

    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接