PersistenceConstructor参数变量名称与实例变量名称不匹配 [英] PersistenceConstructor argument variable name doesn't match instance variable name

查看:252
本文介绍了PersistenceConstructor参数变量名称与实例变量名称不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 spring-data-mongodb 版本 1.1.1.RELEASE 来保留以下对象:

I'm trying to persist the following object with spring-data-mongodb version 1.1.1.RELEASE:

@Document
public static class TestObject {

    private final int m_property;

    @PersistenceConstructor
    public TestObject(int a_property) {
        m_property = a_property;
    }

    public int property() {
        return m_property;
    }

}

我得到 MappingException 当我尝试从数据库中读回对象时(参见下面的完整堆栈跟踪)

I get a MappingException when I try to read the object back from the database (see full stacktrace below)

我的组使用的命名约定需要参数变量名由 a _ 开头,实例变量名由 m _ 开头。似乎 spring-data-mongodb 假设构造函数参数变量名必须与对象实例变量名匹配。

The naming convention my group uses requires argument variable names to be prefaced by a_ and instance variable names to be prefaced by m_. It seems like spring-data-mongodb is making the assumption that the constructor argument variable names must match the object instance variable names.


  • 为什么 spring-data-mongodb 将构造函数参数用于实例我在构造函数中定义的变量映射?

  • 是否有另一种方法来定义此映射,以便 spring-data-mongodb 将正确构建我的对象,或者是我唯一的选择打破命名惯例?

  • Why doesn't spring-data-mongodb use the constructor argument to instance variable mapping that I define within the constructor?
  • Is there another way to define this mapping such that spring-data-mongodb will properly construct my object, or is my only option to break the naming convention?

Exception in thread "main" org.springframework.data.mapping.model.MappingException: No property a_property found on entity class com.recorder.TestRecorder$TestObject to bind constructor parameter to!
    at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:90)
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:70)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:229)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:209)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:173)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:169)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:72)
    at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:1820)
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1542)
    at org.springframework.data.mongodb.core.MongoTemplate.findAll(MongoTemplate.java:1064)
    at com.recorder.TestRecorder.main(TestRecorder.java:43)


推荐答案

tl; dr

我们需要依赖构造函数参数名称来匹配字段名称,以找出要引入的文档的哪个字段。如果要自定义此构造函数参数,请使用 @Value(#root.field_name)

We need to rely on constructor argument names to match field names to find out which field of the document to pull in. If you want to customize this use @Value("#root.field_name") on the constructor argument.

长篇故事

如果您使用带参数的构造函数让Spring Data使用此构造函数实例化给定的类,我们必须将参数传递给调用时的构造函数。要找出我们必须提交的文档字段,我们需要检查匹配属性以进行潜在的字段名称自定义。请参阅以下示例:

If you're using a constructor with arguments to let Spring Data instantiate the given class using this constructor we have to hand parameters to the constructor upon invocation. To find out which document field we have to hand in, we need to inspect the matching property for potential field name customization. See the following example:

@Document
class MyEntity {

  @Field("foo")
  private String myField;

  public MyEntity(String myField) {
    this.myField = myField;
  }
}

在这种情况下,我们需要管道字段 foo 进入构造函数,如果我们不能以某种方式获取对该属性的引用,则无法找到相关内容。如果构造函数参数名称不同,我们应该如何可靠地找出实际上应该将哪个字段值用作参数?您在问题中显示的示例永远不会开箱即用,因为您的文档将包含 m_property 字段,并且绝对没有办法找出你真的想要注入,除了添加更明确的配置。

In this case we need to pipe the field foo into the constructor and there's no way to find out about this if we don't somehow can obtain a reference to the property. If the constructor parameter name was something different, how should we reliably find out which field value should actually be used as argument? The example you've shown in your question can never work out of the box, as your document would contain a m_property field and there's absolutely no way to find out you actually want that to be injected, except adding more explicit configuration.

要自定义此行为,您可以使用Spring的 @Value 注释并将自定义文档字段注入构造函数。文档本身可通过 #root 变量获得。因此,您可以轻松地将上面的示例更改为:

To customize this behavior you can use Spring's @Value annotation and inject a custom document field into the constructor. The document itself is available through the #root variable. So you could easily alter my sample above to:

@Document
class MyEntity {

  @Field("foo")
  private String myField;

  public MyEntity(@Value("#root.foo") String somethingDifferent) {
    this.myField = somethingDifferent;
  }
}

我强烈建议您添加自定义字段名称您的属性以及您不希望将属性命名约定公开给数据库。用法pf @Value 参考文档但我创建了一张票据,用于改进文档并使其更加明显。

I'd strongly recommend that you add custom field names to your properties as well as you don't want to expose your property naming conventions to the database. The usage pf @Value is briefly mentioned in the reference docs but I've created a ticket to improve the docs and make this more obvious.

这篇关于PersistenceConstructor参数变量名称与实例变量名称不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆