@Service
public abstract class BaseService<R extends IChanakyaR2dbcRepository<E, String>, E, D> {
@Autowired
protected R repository;
public abstract D convertToDTO(E entity);
public abstract E convertToEntity(D DTO);
public Flux<D> findAll() {
return repository.findAll().map(this::convertToDTO);
}
public Mono<D> findById(String id) {
return repository.findById(id).map(this::convertToDTO);
}
public Mono<D> create(D DTO) {
return repository.insert(convertToEntity(DTO)).map(this::convertToDTO);
}
public Mono<D> update(D DTO) {
return repository.save(convertToEntity(DTO)).map(this::convertToDTO);
}
public Mono<Void> delete(D DTO) {
return repository.delete(convertToEntity(DTO));
}
}
У меня есть вышеуказанный класс как абстрактный класс, от которого будут наследоваться все мои базовые классы услуг.
@Service
public class ClusterService extends BaseService<IChanakyaR2dbcRepository<ClusterEntity, String>, ClusterEntity, ClusterDTO> {
@Autowired
ModelMapper modelMapper;
@Override
public ClusterDTO convertToDTO(ClusterEntity entity) {
return modelMapper.map(entity, ClusterDTO.class);
}
@Override
public ClusterEntity convertToEntity(ClusterDTO DTO) {
return modelMapper.map(DTO, ClusterEntity.class);
}
}
Это мой класс обслуживания.
@NoRepositoryBean
public interface IChanakyaR2dbcRepository<T, ID> extends ReactiveCrudRepository<T, ID> {
/**
* Inserts a given entity. Use the returned instance for further operations as the save operation might have changed the
* entity instance completely.
*
* @param entity must not be {@literal null}.
* @return {@link Mono} emitting the inserted entity.
* @throws IllegalArgumentException in case the given {@literal entity} is {@literal null}.
*/
<S extends T> Mono<S> insert(S entity);
}
Это мой класс хранилища.
@Slf4j
@Transactional(readOnly = true)
public class ChanakyaR2dbcRepository<T, ID> extends SimpleR2dbcRepository<T, ID> {
private final RelationalEntityInformation<T, ID> entity;
private final DatabaseClient databaseClient;
private final R2dbcConverter converter;
private final ReactiveDataAccessStrategy accessStrategy;
public ChanakyaR2dbcRepository(RelationalEntityInformation entity, DatabaseClient databaseClient, R2dbcConverter converter, ReactiveDataAccessStrategy accessStrategy) {
super(entity, databaseClient, converter, accessStrategy);
this.entity = entity;
this.databaseClient = databaseClient;
this.converter = converter;
this.accessStrategy = accessStrategy;
}
@Transactional
public <S extends T> Mono<S> insert(S objectToSave) {
Assert.notNull(objectToSave, "Object to insert must not be null!");
try {
return this.databaseClient.insert()
.into(this.entity.getJavaType())
.table(this.entity.getTableName()).using(objectToSave)
.map(this.converter.populateIdIfNecessary(objectToSave))
.first()
.defaultIfEmpty(objectToSave);
} catch(DataIntegrityViolationException diex) {
String errMsg = String.format("Entity {} already exists in database", this.entity);
log.error(errMsg, diex);
return Mono.error(new IllegalStateException(errMsg));
}
}
}
Это моя реализация хранилища.
Когда я запускаю приложение, я получаю следующую ошибку.
org. springframework.beans.factory.UnsatisfiedDependencyException: Ошибка создания компонента с именем clusterService: неудовлетворенная зависимость, выраженная через поле «хранилище»; вложенное исключение -
org.springframework.beans.factory.NoSuchBeanDefinitionException: нет квалифицированного компонента типа 'com.appdynamics.sum.chanakya.repository.base.IChanakyaR2dbcRepository': ожидается, что по крайней мере 1 компонент, который квалифицируется кандидат. Аннотации зависимостей: {@ org.springframework.beans.factory.annotation.Autowired (обязательно = true)}
Вышеуказанное автоматическое подключение не работает, но когда я автоматически подключаю IChanakyaR2dbcRepository<ClusterEntity, String>
в другом компоненте enet напрямую (не через тип c). Это работает нормально.
Как правильно сделать такую вещь? Я хочу иметь реализацию BaseService.
Я знаю, если вы создадите интерфейс, расширяющий IChanakyaR2dbcRepository<ClusterEntity, String>
, и передадите этот класс как тип c generic в BaseService
, тогда он будет работать нормально. Но это будет означать создание таких пустых классов для каждой имеющейся у меня сущности, которая не является идеальным решением.