Как расширить CassandraRepository

Как мне расширить CassandraRepository в spring-data-cassandra?
Я пробовал так много разных комбинаций, чтобы заставить это работать, в конечном итоге я получил ниже.

User.java

@Table(name = User.TABLE)
public class User {
  private static final String TABLE = "user";

  @PartitionKey
  private UUID id;

  @Column
  private String name;

  // Getter setter methods
  ...
}

CassandraRepositoryCustom.java

@NoRepositoryBean
public interface CassandraRepositoryCustom<T> extends CassandraRepository<T> {
  public T save(T t, Options options);
}

CassandraRepositoryImpl.java

public class CassandraRepositoryImpl<T> 
 extends SimpleCassandraRepository<T, MapId> 
 implements CassandraRepositoryCustom<T> {

  public CassandraRepositoryImpl(CassandraEntityInformation<T, MapId> metadata, 
                                 CassandraOperations operations) {
    super(metadata, operations);
  }

  @Override
  public T save(T t, Options options) {
    ...
  }
}

UserRepositoryCustom.java

public interface UserRepositoryCustom extends CassandraRepositoryCustom<User> {
  User findById(UUID id);
}

UserRepositoryImpl.java

public class UserRepositoryImpl 
 extends CassandraRepositoryImpl<User> 
 implements CassandraRepositoryCustom<User> {

    public UserRepositoryImpl(CassandraEntityInformation<T, MapId> metadata, 
                              CassandraOperations operations) {
      super(metadata, operations);
  }

}

UserDao.java

@Component
public class UserDao {

  @Autowired
  private UserRepositoryCustom repo;

  public save(User user, Options options) {
    repo.save(user, options);
  }

  public getUser(UUID id) {
    repo.findById(id);
  }

}

CassandraConfig.java

@Configuration
@EnableCassandraRepositories(repositoryBaseClass = CassandraRepositoryImpl.class)
public class CassandraConfig {
  ...
}

Теперь все, с чем я столкнулся, это следующее исключение

Вызвано: org.springframework.beans.factory.BeanCreationException: ошибка создания bean-компонента с именем userRepositoryCustom: не удалось вызвать метод инициализации; вложенное исключение - org.springframework.data.mapping.PropertyReferenceException: для типа User не найдено сохранение свойства!


person kalypzo    schedule 06.12.2016    source источник


Ответы (1)


Вы можете настроить репозитории Spring Data двумя способами:

  1. Добавление одного или нескольких пользовательских методов во все репозитории
  2. Добавление одного или нескольких пользовательских методов в отдельные репозитории

Из приведенного выше кода я понимаю, что вы пытаетесь добавить методы, которые должны быть доступны для нескольких репозиториев. Справочная документация содержит руководство по настройке отдельных репозиториев.

Добавление одного или нескольких пользовательских методов во все репозитории

Для добавления метода во все репозитории необходимо выполнить четыре шага. Этот подход удобен, если вы хотите предоставить общий метод, к которому можно получить доступ из нескольких репозиториев, например, в вашем примере с save(T, Options).

  1. Добавление базового класса, который расширяет SimpleCassandraRepository и содержит методы, которые вы планируете предоставить.

    public class MyCustomizedCassandraRepository<T>
                                extends SimpleCassandraRepository<T, MapId>
                                implements MyCassandraRepository<T> {
    
        public MyCustomizedCassandraRepository(CassandraEntityInformation<T, MapId> metadata,
                                                        CassandraOperations operations) {
            super(metadata, operations);
        }
    
        public T save(T entity, WriteOptions options) {
    
            System.out.println(String.format("Called MyCustomizedCassandraRepository.save(%s, %s)", 
                                                 entity, options));
            return entity;
        }
    }
    
  2. Настройте базовый класс в @EnableCassandraRepositories

    @SpringBootApplication
    @EnableCassandraRepositories(repositoryBaseClass = MyCustomizedCassandraRepository.class)
    public class DemoApplication {
        // ...
    }
    
  3. Теперь создайте интерфейс, объявляющий раскрываемый вами метод. Это позволяет вам расширять базовый интерфейс вместо того, чтобы объявлять метод в каждом репозитории, но это полностью зависит от вас.

    @NoRepositoryBean
    public interface MyCassandraRepository<T> extends CassandraRepository<T> {
    
        /**
         * Customized save method.
         */
         T save(T entity, WriteOptions options);
    }
    
  4. Объявите интерфейсы репозитория, расширив базовый интерфейс

    interface UserRepository extends MyCassandraRepository<User> {
    }
    

Нет никаких строгих правил относительно наименования. Важными битами являются установка repositoryBaseClass в @EnableCassandraRepositories и совпадение имени метода / типа параметра между базовым методом и методом интерфейса репозитория.

Я создал исполняемый пример, который настраивает базовый класс репозитория. Найдите ссылку в конце этого сообщения.

Замечания

Код сверху не компилируется (из-за public UserRepositoryImpl(CassandraEntityInformation<T, MapId> metadata) и не приводит к PropertyReferenceException.

Смотрите также:

person mp911de    schedule 06.12.2016
comment
Спасибо, но у меня все еще возникают проблемы. - person kalypzo; 06.12.2016
comment
Предоставьте воспроизводимый тестовый пример (Github Repo или Gist). - person mp911de; 06.12.2016
comment
Понял, я предоставлю один, а также обновлю вопрос здесь - person kalypzo; 06.12.2016
comment
У меня здесь репо: github.com/kalypzo/example-spring И суть здесь: gist.github.com/kalypzo/5dbdef83632b22e4d2e6e0686e Теперь я сконструировал параметр 03 из com.example.repository.UserRepositoryImpl требовал bean-объекта типа org.springframework.data.cassandra.repository.query.CassandraEntityInformation, который не удалось найти. Но мне нужно, чтобы эта CassandraEntityInformation была динамической на основе Entity. - person kalypzo; 06.12.2016
comment
Ваш пример содержит настройку как единого репозитория, так и базового репозитория. Переместите @EnableCassandraRepositories(repositoryBaseClass = CassandraCrudRepositoryImpl.class) из CassandraConfig в Startup и сделайте UserRepositoryImpl Pojo / удалите конструктор (т.е. не расширяющийся от CassandraCrudRepositoryImpl). UserRepository уже набрано User. CassandraCrudRepositoryImpl по-прежнему создается с CassandraEntityInformation и будет правильно подключен. Хранилища данных Spring используют прокси для маршрутизации вызовов методов к соответствующей цели. - person mp911de; 06.12.2016
comment
Кажется, это сработало, не знаю, почему мне пришлось поместить EnableCassandraRepositories в Startup vs CassandraConfig, но это определенно сработало! - person kalypzo; 07.12.2016
comment
@EnableCassandraRepositories принимает без какой-либо дополнительной настройки базовый пакет вашего @Configuration класса в качестве корня сканирования. Размещение @EnableCassandraRepositories с repositoryBaseClass, настроенным на CassandraConfig, регистрирует только репозитории, расположенные ниже com.example.config. Для всех остальных репозиториев применяются значения по умолчанию. Возможная альтернатива - настройка basePackageClasses = CassandraCrudRepository.class - person mp911de; 07.12.2016
comment
Спасибо @ mp911de. Вы сэкономили мне много времени. Я совершал ту же ошибку. - person Krish; 17.12.2020