是否有一种简单的方法可以将spring数据沙发基础与没有_class
属性的文档一起使用?
在沙发基地,我在sampledata
桶中有这样的东西:
{
"username" : "alice",
"created" : 1473292800000,
"data" : { "a": 1, "b" : "2"},
"type" : "mydata"
}
现在,有没有办法定义从这个文档结构到Java对象的映射(请注意_class
属性缺失且无法添加),反之亦然,以便我获得所有(或大多数)自动化功能从spring couchbase数据?
像:
如果type
字段的值为“mydata”,则使用类MyData.java。
因此,执行查找时,不会自动将AND _class = "mydata"
添加到生成的查询添加AND type = "mydata"
。
答案 0 :(得分:5)
Spring数据通常需要_class
字段来知道反序列化时要实例化的内容。
通过覆盖_class
中的typeKey()
方法,Spring Data Couchbase使用与AbsctractCouchbaseDataConfiguration
不同的字段名称相当容易。
但它仍然会在默认情况下期望完全限定的类名
绕过这将需要更多的工作:
CouchbaseTypeMapper
的模型实施自己的DefaultCouchbaseTypeMapper
。在super(...)
构造函数中,您需要提供一个额外的参数: TypeInformationMapper
的列表。默认实现没有明确提供一个,因此使用SimpleTypeInformationMapper
,这是放置FQN的那个。Map
将特定类别名为较短的名称:ConfigurableTypeInformationMapper
... ConfigurableTypeInformationMapper
,其中包含您想要的特定类别的别名+ SimpleTypeInformationMapper
(对于这种情况,您序列化了一个您没有为其提供别名的类别),你可以实现你的目标。typeMapper
用于MappingCouchbaseConverter
,您还需要进行扩展(仅用于实例化typeMapper
而不是默认值。MappingCouchbaseConverter
(CouchbaseTypeMapper
方法)的自定义mappingCouchbaseConverter()
实例。答案 1 :(得分:2)
例如,您可以实现通过创建自定义注释@DocumentType
@DocumentType("billing")
@Document
public class BillingRecordDocument {
String name;
// ...
}
文档外观如下:
{
"type" : "billing"
"name" : "..."
}
只需创建以下类:
创建自定义AbstractReactiveCouchbaseConfiguration
或AbstractCouchbaseConfiguration
(取决于您使用的瓦里安)
@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'
}
}
创建自定义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);
}
}
和自定义注释@DocumentType
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface DocumentType {
String value();
}
然后创建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);
}
}
然后将其注册如下
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;
}
}
答案 2 :(得分:1)
在您的couchbase配置类中,您只需要:
composer.navigationBar.barTintColor
不幸的是,对于查询派生(n1ql),_class或类型仍在使用类名.Tried spring couch 2.2.6及其在此处的减号。 @Simon,您是否知道某些内容已发生变化,并支持在下一个版本中拥有自定义_class / type值?
答案 3 :(得分:1)
@SimonBasle 在类N1qlUtils和方法createWhereFilterForEntity中,我们可以访问CouchbaseConverter。在线:
String typeValue = entityInformation.getJavaType().getName();
当我们要避免使用类名时,为什么不使用转换器中的typeMapper获取实体的名称呢?否则,您必须注释存储库中的每个方法,如下所示:
@Query("#{#n1ql.selectEntity} WHERE `type`='airport' AND airportname = $1")
List<Airport> findAirportByAirportname(String airportName);
如果createWhereFilterForEntity使用了CouchbaseConverter,我们可以避免使用@Query进行注释。