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 映射中查询 KV 对。我收到一个错误:No mapping metadata found for java.lang.Object

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

编辑

存储在 Couchbase 中的数据:

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

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

4

2 回答 2

5

正如这里所解释的,您应该覆盖默认的 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);
        }
    }

}
于 2016-04-26T14:26:46.293 回答
0

如果您绝对需要Map

看起来问题是双重的:

  1. 在我的测试中,使用带参数的构造函数通过反射重新实例化似乎效果不佳,因此我将添加一个私有的空构造函数private GsJsonStore() {}
  2. 您存储的Map包含另一个级别的嵌套,也是通用Map的。这对于框架在反序列化时处理是有问题的。

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

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

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

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

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与作为参数传递的字符串相同的值的字段。

于 2016-03-15T11:34:18.043 回答