Общий тип в хранилище для couchbase с использованием пружинной загрузки - PullRequest
6 голосов
/ 10 октября 2019

Я создаю утилиту в Spring Boot для подключения и вставки / вставки данных в базу данных более общим способом.

У меня есть что-то вроде этого:

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

Там, где у меня есть MyClass, я хотел бы принять любой тип документа для вставки в базу.

Я пробовал некоторые вещи, такие как использование универсального типа T, но безуспешно, потому что я получилследующая ошибка:

Причина: org.springframework.data.mapping.MappingException: Не удалось найти PersistentEntity для класса типа java.lang.Object!

Моя структураis: service (interface / impl)> DAO (interface / impl)> репозиторий

Дополнительная информация: через вышеупомянутую модель я передаю универсальный тип T. Я вызываю службу с моим Pojo с @Document annotation.

Цель состоит в том, чтобы устранить «зависимость» наличия одного класса репозитория для каждого типа документа.

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

Вы можете иметь общие репозитории (немного хакерские), но с некоторыми ограничениями. Предположим, у вас есть документы;

@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 Mid1 и Mid1 extends Base)

1 голос
/ 11 октября 2019

Я не думаю, что это возможно с помощью 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));
...