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

找不到java.lang.Object-Couchbase的映射元数据,couchbase,spring-data-couchbase,Couchbase,Spring Data Couchbase,我正在CouchBase存储库中持久化一个实体并尝试查询它。实体如下所示: @Document(expiry = 0) public class GsJsonStore implements Serializable { private static final long serialVersionUID = 7133072282172062535L; @Id @GeneratedValue(strategy=GenerationType.AUTO) private lo

我正在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 
    }
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.Name和value是'Kapil'

如果您绝对需要
地图

看起来问题有两方面:

  • 在我的测试中,使用带参数的构造函数通过反射重新实例化似乎效果不太好,因此我要添加一个私有空构造函数
    private GsJsonStore(){}
  • 存储的
    Map
    还包含另一个嵌套级别,作为通用
    Map
    。这对于框架在反序列化时处理是有问题的
  • 您可以尝试将“Age”展平到顶级
    \u对象
    映射中,或者为“Age”条目创建一个专用类(只需使用int类型的
    嵌套
    字段)并将其存储。请注意,在后一种情况下,框架应该将
    \u class
    元数据添加到存储的“Age”JSON中,这解释了在这种情况下,框架如何在稍后对其进行反序列化

    如果您可以比
    地图更具体地建模

    最好的方法仍然是创建一个适当的
    GsEntity
    类,该类没有通用的集合/映射,但有命名的属性(可能还有子值的有意义的实体类)

    这将缓解
    Map
    s的问题,并允许通过简单地在存储库接口中添加方法签名来自动创建查询。诸如此类:

    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);
    }
    
    公共类ContentObject{
    私有字符串名称;
    私人互联网;
    公共ContentObject(字符串名,int-age){
    this.name=名称;
    这个。年龄=年龄;
    }
    }
    @文件(到期日=0)
    公共类GsEntity实现可序列化{
    私有静态最终长serialVersionUID=71330722172062535L;
    @身份证
    私有字符串id;
    @场
    私有内容对象;
    @场
    私有字符串主题;
    @场
    私有字符串谓词;
    //空构造函数
    //接球手和接球手
    }
    公共接口GsEntityRepository扩展了CouchbaseRepository{
    @质疑
    列出findByObjectNameEquals(字符串名称值);
    }
    
    请注意,属性已重命名以删除下划线,因为它不遵循Java命名约定,并且会阻止接口的方法正确映射到属性

    该方法的分析大致如下:
    通过
    对象
    名称
    等于

    这将转换为一组选择的
    GsEntity
    对象,其中
    对象
    字段具有一个
    名称
    字段,该字段的值与作为参数传递的字符串的值相同。

    如果您绝对需要
    映射

    看起来问题有两方面:

  • 在我的测试中,使用带参数的构造函数通过反射重新实例化似乎效果不太好,因此我要添加一个私有空构造函数
    private GsJsonStore(){}
  • 存储的
    Map
    还包含另一个嵌套级别,作为通用
    Map
    。这对于框架在反序列化时处理是有问题的
  • 您可以尝试将“Age”展平到顶级
    \u对象
    映射中,或者为“Age”条目创建一个专用类(只需使用int类型的
    嵌套
    字段)并将其存储。请注意,在后一种情况下,框架应该将
    \u class
    元数据添加到存储的“Age”JSON中,这解释了在这种情况下,框架如何在稍后对其进行反序列化

    如果您可以比
    地图更具体地建模

    最好的方法仍然是创建一个适当的
    GsEntity
    类,该类没有通用的集合/映射,但有命名的属性(可能还有子值的有意义的实体类)

    这将缓解
    Map
    s的问题,并允许通过简单地在存储库接口中添加方法签名来自动创建查询。诸如此类:

    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);
    }
    
    公共类ContentObject{
    私有字符串名称;
    私人互联网;
    公共ContentObject(字符串名,int-age){
    this.name=名称;
    这个。年龄=年龄;
    }
    }
    @文件(到期日=0)
    公共类GsEntity实现可序列化{
    私有静态最终长serialVersionUID=71330722172062535L;
    @身份证
    私有字符串id;
    @场
    私有内容对象;
    @场
    私有字符串主题;
    @场
    私有字符串谓词;
    //空构造函数
    //接球手和接球手
    }
    公共接口GsEntityRepository扩展了CouchbaseRepository{
    @质疑
    列出findByObjectNameEquals(字符串名称值);
    }
    
    请注意,属性已重命名以删除下划线,因为它不遵循Java命名约定,并且会阻止接口的方法正确映射到属性

    该方法的分析大致如下:
    通过
    对象
    名称
    等于
    。 这将转换为一组选定的
    GsEntity
    对象,其中
    object
    字段有一个
    name
    字段,该字段的值与作为参数传递的字符串的值相同。

    如前所述,您应该覆盖默认的SPCMappingCouchBaseConverter

    下面是我如何解决这个问题的:

    @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);
            }
        }
    
    }
    
    @Bean
    公共MappingCouchbaseConverter MappingCouchbaseConverter()引发异常{
    返回新的MyMappingCouchbaseConverter(couchbaseMappingContext());
    }
    私有类MyMappingCouchbaseConverter扩展了MappingCouchbaseConverter{
    MyMappingCouchbaseConverter(MappingContext,CouchbasePersistentProperty>MappingContext){
    super(mappingContext);
    }
    @凌驾
    @抑制警告(“未选中”)
    受保护的R读(最终类型信息类型,最终C