Generic type to repository for couchbase using spring boot

Fabio Cardoso :

I'm creating an utility in Spring Boot to connect and insert/upsert data into the couchbase in the more generic way possible.

I have something like this:

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

Where I have MyClass I would like to accept any kind of document to insert into couchbase.

I have tried some things like using the generic type T but without success because I got the following error:

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

My structure is: service (interface/impl) > DAO (interface/impl) > repository

Extra info: Across the above model I am passing a Generic type T. I am calling the service with my Pojo with the @Document annotation.

The goal is to remove the "dependency" of having one repository class for each type of Document.

buræquete :

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)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=304987&siteId=1