使用 spring 启动的 couchbase 存储库的通用类型

Generic type to repository for couchbase using spring boot

我正在 Spring Boot 中创建一个实用程序,以尽可能更通用的方式将 insert/upsert 数据连接到 couchbase。

我有这样的东西:

public interface GenericRepository extends CouchbaseRepository<MyClass, String> {
}

我有 MyClass 我愿意接受 任何类型 的文件插入沙发底座。

我尝试了一些方法,例如使用泛型类型 T 但没有成功,因为我收到以下错误:

Caused by: org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type class java.lang.Object!

我的结构是:service (interface/impl) > DAO (interface/impl) > repository

额外信息:在上述模型中,我传递了一个通用类型 T。我正在使用带有 @Document 注释的 Pojo 调用该服务。

我们的目标是消除 "dependency" 每种类型的文档都有一个存储库 class。

更新:您可以构建一个 class,它通过 CouchbaseOperations class 对实体 (save/delete/update) 进行通用操作。您需要做的就是将其注入您的服务或自定义存储库。

我不认为这可以通过 Spring SDK 实现(Couchbase 只是实现了 Spring 的规范)。但是,您可以使用反射和标准 Java SDK:

创建单个通用存储库
    Cluster cluster = CouchbaseCluster.create("localhost");
    cluster.authenticate("username", "password");
    Bucket bucket = cluster.openBucket("bucketname");

    // Create a JSON Document
    JsonObject arthur = JsonObject.create()
        .put("name", "Arthur")
        .put("email", "kingarthur@couchbase.com")
        .put("interests", JsonArray.from("Holy Grail", "African Swallows"));

    // Store the Document
    bucket.upsert(JsonDocument.create("u:king_arthur", arthur));

您可以拥有通用存储库(有点老套)但有一些限制。假设您有文件;

@Document
public class MyClass1 extends BaseClass {

    private String text1;

    public MyClass1() {
        super();
        setType(Type.MyClass1);
    }

    // getter/setters
}

@Document
public class MyClass2 extends BaseClass {

    private String text2;

    public MyClass2() {
        super();
        setType(Type.MyClass2);
    }

    // getter/setters
}

BaseClass

@Document
public class BaseClass { 

    private Type type;

    // other common fields if any, and getter/setters

    public enum Type {
        MyClass1, MyClass2
    }
}

那么你可以拥有以下存储库;

public interface GenericRepository<T extends BaseClass> extends CouchbaseRepository<T, String> {

    public List<T> findByType(BaseData.Type type);

    public default List<T> findAll(Class<T> clazz) throws IllegalAccessException, InstantiationException {
        return findByType(clazz.newInstance().getType());
    }
}

并喜欢使用它;

@Autowired
private GenericRepository<MyClass1> mc1Repository;
@Autowired
private GenericRepository<MyClass2> mc2Repository;

public void doStuff() {
    MyClass1 myClass1 = new MyClass1();
    myClass1.setText1("text1");
    mc1Repository.save(myClass1);
    mc1Repository.findAll(MyClass1.class).forEach(d -> System.out.println(d.getText1()));

    MyClass2 myClass2 = new MyClass2();
    myClass2.setText2("text2");
    mc2Repository.save(myClass2);
    mc2Repository.findAll(MyClass2.class).forEach(d -> System.out.println(d.getText2()));
}

会打印出来;

text1
text2

但请注意,文档将全部在同一个集合中,即 BaseClass

的集合

此外,这不适用于多个扩展名(例如 MyClass1 extends Mid1Mid1 extends Base