Generic type to repository for couchbase using spring boot

UPDATE: You can build a class that does generic manipulation of an entity (save/delete/update) via the CouchbaseOperations class. All you need to do is to inject it in your service or custom repository.

I don't think this is possible via the Spring SDK (Couchbase just implements the Spring's spec). However, you can create a single generic repository using reflection and the standard 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", "[email protected]")
        .put("interests", JsonArray.from("Holy Grail", "African Swallows"));

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

You can have generic repositories (bit hacky) but with some limitation. Assume you have documents;

@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
}

with BaseClass;

@Document
public class BaseClass { 

    private Type type;

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

    public enum Type {
        MyClass1, MyClass2
    }
}

Then you can have the following repository;

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());
    }
}

and use it like;

@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()));
}

will print out;

text1
text2

But be aware that the documents will be all in same collection that is the collection for the BaseClass

Also this won't work with more than one extension (like MyClass1 extends Mid1, and Mid1 extends Base)