首页 文章

找不到java.lang.Object的映射元数据 - Couchbase

提问于
浏览
0

我在CouchBase存储库中持久化实体并尝试查询它 . 该实体看起来像这样:

@Document(expiry = 0)
public class GsJsonStore implements Serializable {
    private static final long serialVersionUID = 7133072282172062535L;
    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    @Field
    private Map<String,Object> _object;
    @Field
    private String _subject;
    @Field
    private String _predicate;
    //Getters and Setters 
    }

我在CouchbaseOperations模板上使用N1QL查询来查询实体,如下所示:

String query1 =  "SELECT META(default).id as _ID, META(default).cas as _CAS, default.* FROM default WHERE "+key+"="+"'"+value+"'";

List<GsJsonStore> list = operations.findByN1QL(N1qlQuery.simple(query1), GsJsonStore.class);

我在_object Map中查询K-V对 . 我收到一个错误: No mapping metadata found for java.lang.Object

为什么会这样?另外,我将一个json对象存储为Couchbase中的 Map<String,Object> ,我尝试使用jackson JsonNode 类型,但该对象也存储了类相关的元数据 . 是否有更好的数据类型来表示json类型?

EDIT

存储在Couchbase中的数据:

{
"_object" : {
"Name" : "Kapil",
"Age" : {
"Nested" : 21
}
},
"_subject" : "Subject",
"_predicate" : "Predicate"
}

我正在寻找的关键是_object.Name,值是'Kapil'

2 回答

  • 0

    正如here所解释的那样,您应该覆盖默认的SPMappingCouchbaseConverter .

    这是我解决问题的方法:

    @Bean
    public MappingCouchbaseConverter mappingCouchbaseConverter() throws Exception {
        return new MyMappingCouchbaseConverter(couchbaseMappingContext());
    }
    
    private class MyMappingCouchbaseConverter extends MappingCouchbaseConverter {
    
        MyMappingCouchbaseConverter(MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext) {
            super(mappingContext);
        }
    
        @Override
        @SuppressWarnings("unchecked")
        protected <R> R read(final TypeInformation<R> type, final CouchbaseDocument source, final Object parent) {
            if (Object.class == typeMapper.readType(source, type).getType()) {
                return (R) source.export();
            } else {
                return super.read(type, source, parent);
            }
        }
    
    }
    
  • 5

    If you absolutely need the Map

    看起来问题是双重的:

    • 通过反射使用带参数的构造函数重新实例化't seem to work that well from my tests, so I' d添加一个私有的空构造函数 private GsJsonStore() {} .

    • 您存储的 Map 包含另一级别的嵌套,也是一般的 Map . 这对于在反序列化时处理的框架是有问题的 .

    您可以尝试将"Age"展平到顶级 _object Map 中,或者为"Age"条目创建一个专用类(只需使用int类型的 Nested 字段)并存储它 . 请注意,在后一种情况下,框架应该将 _class 元数据添加到存储的"Age" JSON中,这解释了在这种情况下它如何设法在以后对其进行反序列化 .

    If you can modelize more specifically than a Map

    最好的方法仍然是创建一个没有泛型集合/映射但是命名属性的正确 GsEntity 类(也可能是子值的有意义的实体类) .

    这将缓解 Map 的问题,并允许通过在存储库接口中添加方法签名来自动创建查询 . 像这样的东西:

    public class ContentObject {
    
        private String name;
        private int age;
    
        public ContentObject(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    
    @Document(expiry = 0)
    public class GsEntity implements Serializable {
    
        private static final long serialVersionUID = 7133072282172062535L;
    
        @Id
        private String id;
    
        @Field
        private ContentObject object;
    
        @Field
        private String subject;
    
        @Field
        private String predicate;
    
        //EMPTY CONSTRUCTOR
    
        //Getters and Setters 
    }
    
    public interface GsEntityRepository extends CouchbaseRepository<GsEntity, String> {
    
        @Query
        List<GsEntity> findByObjectNameEquals(String nameValue);
    }
    

    请注意,已重命名属性以删除下划线,因为它不遵循Java命名约定,并且会阻止接口的方法正确映射到属性 .

    该方法大致分析如下: findBy Object Name Equals . 这转换为 GsEntity 对象的SELECT,其中 object 字段具有 name 字段,该字段与作为参数传递的字符串具有相同的值 .

相关问题