如何在不具有_class属性的情况下将Spring数据与Couchbase一起使用

Mil*_*lan 4 java couchbase spring-data spring-data-couchbase

有没有一种简单的方法可以将spring数据更新到没有_class属性的文档中?在沙发上,我的sampledata水桶里有这样的东西:

{
  "username" : "alice", 
  "created" : 1473292800000,
  "data" : { "a": 1, "b" : "2"},
  "type" : "mydata"
}
Run Code Online (Sandbox Code Playgroud)

现在,是否有任何方法可以定义从此文档结构到Java对象的映射(请注意,_class缺少属性并且无法添加属性),反之亦然,这样我就可以从Spring Couchbase数据中获取所有(或大多数)自动魔术功能?

诸如此类:如果type字段的值为“ mydata”,请使用类MyData.java。因此,当执行查找而不是自动添加AND _class = "mydata"到生成的查询add时AND type = "mydata"

Sim*_*slé 5

通常,Spring Data需要该_class领域知道反序列化时要实例化的内容。

_class通过覆盖中的typeKey()方法,在Spring Data Couchbase中使用不同的字段名称非常容易AbsctractCouchbaseDataConfiguration

但是默认情况下,仍然需要一个完全合格的类名

解决这个问题将需要更多的工作:

  1. 您需要CouchbaseTypeMapper遵循的模型来实现自己的模型DefaultCouchbaseTypeMapper。在super(...)构造函数中,您需要提供一个附加参数:的列表TypeInformationMapper。默认实现未明确提供一个,因此使用a SimpleTypeInformationMapper,即放置FQN的实现。
  2. 还有一个可配置的替代实现,因此您可以通过MapConfigurableTypeInformationMapper...将特定的类别名为较短的名称。
  3. 因此,通过在列表中放置一个ConfigurableTypeInformationMapper您想要的用于特定类的别名+一个SimpleTypeInformationMapper在其后的别名(对于序列化一个您没有为其提供别名的类的情况),可以实现您的目标。
  4. 不幸的typeMapperMappingCouchbaseConverter,您还需要扩展typeMapper,在中使用。(只是实例化您的默认值。
  5. 完成后,再次覆盖配置以返回MappingCouchbaseConverter使用您的自定义CouchbaseTypeMappermappingCouchbaseConverter()方法)的自定义实例。

  • 正确,目前无​​法使用AFAIK,或者至少没有正式支持 (2认同)

Pet*_*vic 5

您可以通过创建自定义注释来实现此目的@DocumentType

@DocumentType("billing")
@Document
public class BillingRecordDocument {
    String name;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

文档将如下所示:

{
    "type" : "billing"
    "name" : "..."
}
Run Code Online (Sandbox Code Playgroud)

只需创建以下类:创建自定义AbstractReactiveCouchbaseConfigurationAbstractCouchbaseConfiguration(取决于您使用的变体)

@Configuration
@EnableReactiveCouchbaseRepositories
public class CustomReactiveCouchbaseConfiguration extends AbstractReactiveCouchbaseConfiguration {
     // implement abstract methods
     // and configure custom mapping convereter
    @Bean(name = BeanNames.COUCHBASE_MAPPING_CONVERTER)
    public MappingCouchbaseConverter mappingCouchbaseConverter() throws Exception {
        MappingCouchbaseConverter converter = new CustomMappingCouchbaseConverter(couchbaseMappingContext(), typeKey());
        converter.setCustomConversions(customConversions());
        return converter;
    }

    @Override
    public String typeKey() {
        return "type"; // this will owerride '_class'
    }
}
Run Code Online (Sandbox Code Playgroud)

创建自定义MappingCouchbaseConverter

public class CustomMappingCouchbaseConverter extends MappingCouchbaseConverter {

    public CustomMappingCouchbaseConverter(final MappingContext<? extends CouchbasePersistentEntity<?>,
            CouchbasePersistentProperty> mappingContext, final String typeKey) {
        super(mappingContext, typeKey);
        this.typeMapper = new TypeBasedCouchbaseTypeMapper(typeKey);
    }
}
Run Code Online (Sandbox Code Playgroud)

和自定义注释@DocumentType

@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface DocumentType {

    String value();

}
Run Code Online (Sandbox Code Playgroud)

然后创建TypeAwareTypeInformationMapper它,仅检查实体是否被注释,@DocumentType如果是,则使用该注释中的值,如果没有则使用默认值(完全限定的类名)

public class TypeAwareTypeInformationMapper extends SimpleTypeInformationMapper {

    @Override
    public Alias createAliasFor(TypeInformation<?> type) {
        DocumentType[] documentType = type.getType().getAnnotationsByType(DocumentType.class);

        if (documentType.length == 1) {
            return Alias.of(documentType[0].value());
        }

        return super.createAliasFor(type);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后注册如下

public class TypeBasedCouchbaseTypeMapper extends DefaultTypeMapper<CouchbaseDocument> implements CouchbaseTypeMapper {

    private final String typeKey;

    public TypeBasedCouchbaseTypeMapper(final String typeKey) {
        super(new DefaultCouchbaseTypeMapper.CouchbaseDocumentTypeAliasAccessor(typeKey),
              Collections.singletonList(new TypeAwareTypeInformationMapper()));
        this.typeKey = typeKey;
    }

    @Override
    public String getTypeKey() {
        return typeKey;
    }
}
Run Code Online (Sandbox Code Playgroud)