We have an interface that extends PagingAndSortingRepository (which in turn extends CrudRepository<T, ID>):
public interface ProductPagingAndSortingRepository<T, ID> extends PagingAndSortingRepository<T, ID> {
Optional<T> findByCompanyIdAndCode(@NotNull Integer companyId, @NotNull String code);
Optional<T> findByCompanyIdAndName(@NotNull Integer companyId, @NotNull String name);
...
}
This interface has several methods for a few entities, which have the same fields (code, name, etc.). We have several interfaces that extend this interface. For example, for make and model we have these implementations without any method:
public interface ProductBrandRepository extends ProductPagingAndSortingRepository<ProductBrand, Integer> {}
public interface ProductModelRepository extends ProductPagingAndSortingRepository<ProductModel, Integer> {}
...
We have a class running in which processes products and in has a method that receives a parameter ProductPagingAndSortingRepository and several fields to filter:
private Object getProductData(final Integer companyId, final ProductPagingAndSortingRepository<?, ?> repository, final String code, final String name) {
Optional<?> optionalProductData = repository.findByCompanyIdAndCode(companyId, code);
if (optionalProductData.isPresent()) {
return optionalProductData.orElse(null);
} else {
optionalProductData = repository.findByCompanyIdAndName(companyId, name);
if (optionalProductData.isPresent()) {
return optionalProductData.orElse(null);
} else {
// code for not found...
}
}
}
In this case, everything works correctly invoking in this way:
ProductBrand productBrand = (ProductBrand) this.getProductData(companyId, productBrandRepository, "code1", "brand1");
ProductModel productModel = (ProductModel) this.getProductData(companyId, productModelRepository, "code2", "model2");
Now, if we do a similar method to save, it indicates the error “Inferred type ‘S’ for type parameter ‘S’ is not within its bound; should extend ‘capture<?>'”:
private Object saveIfNotExists(final Integer companyId, final ProductPagingAndSortingRepository<?, ?> repository, final String code, final String name, final Object product) {
Optional<?> optionalProductData = this.getProductData(companyId, repository, code, name);
if (optionalProductData.isEmpty()) {
repository.save(object); // --> Error
optionalProductData = this.getProductData(companyId, repository, code, name);
}
return optionalProductData.orElse(null);
}
In this case, how could I record that object in the database? This is how we invoke it:
ProductBrand productBrand = (ProductBrand) this.saveIfNotExists(companyId, productBrandRepository, productBrand.getCode(), productBrand);
ProductModel productModel = (ProductModel) this.saveIfNotExists(companyId, productModelRepository, productModel.getName(), productModel.getCode(), productModel);