主要问题 - 我想编写一个服务(比如说CommonService)来处理一系列实体的查找,计数等常见操作(有一个原因我无法使用JpaRepository - 盒子方法,如下所述)。我如何自动装配JpaRepository来实现这一目标?详情 -
并发症 - 现在,由于业务需求,我必须将国家/地区ID与每个实体相关联(保存时使用,并在检索时使用等)。我从登录用户那里得到这个ID(即不作为保存或查询实体的一部分提供) - 所以我不能直接使用(或通过REST公开)JpaRepository save或findOne - 我必须通过一个服务来执行此操作然后使用JpaRepository保存/提取。
技术堆栈
我有一个抽象的基本实体 - Fruit(带@MappedSuperclass),我的所有水果类都延伸 - 例如Apple,Orange等。
我有一个常用方法的BaseRepository -
@NoRepositoryBean
public interface BaseRepository<T> extends JpaRepository<T, Long> {
/* common entity methods here */
T findByIdAndCountryId(Long id, String countryId);
Long countByIdAndCountryId(Long id, String countryId);
}
所有水果库都延伸 -
public interface AppleRepository extends BaseRepository<Apple> {
/* entity specific methods here */
}
public interface OrangeRepository extends BaseRepository<Orange> {
/* entity specific methods here */
}
public interface BananaRepository extends BaseRepository<Banana> {
/* entity specific methods here */
}
public interface GrapeRepository extends BaseRepository<Grape> {
/* entity specific methods here */
}
现在,由于业务需求(在上面的复杂化中已经过时),我必须有一个使用JpaRepository执行save / fetche的服务层。像下面的东西 -
public Fruit findMyFruit(Long id) {
Fruit localFruit;
String countryId = null;
countryId = countryService.GetCountryIdForLoggedInUser();
/* ?? how to autowire repository based on entity ?? */
repository.findByIdAndCountryId(id, countryId);
return localBaseEntity;
}
在上面的例子中,它只是关于获取countryId,其他情况更复杂,因此我不能(或不想)每次在调用控制器或服务等中重复它们。
如果我使用Generics并执行以下操作,Spring不喜欢它 -
public class CommonService<Fruit>{
@Autowired
BaseRepository<Fruit> repository;
}
它给出错误 -
org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有定义[org.springframework.data.jpa.repository.JpaRepository]类型的限定bean:期望的单个匹配bean但找到了4
我可以使其工作的一种方式(我目前所做的)是将实体传递给CommonService中的每个方法,然后根据传递的实体类型(使用instanceof)使用相应的存储库 - 显然这不是最有效的方式 -
switch (determineEntityType(incomingFruit)) {
case APPLE:
localFruit = appleRepository.findByIdAndCountryId(id, countryId);
break;
case ORANGE:
localFruit = orangeRepository.findByIdAndCountryId(id, countryId);
break;
case BANANA:
localFruit = bananaRepository.findByIdAndCountryId(id, countryId);
break;
case GRAPE:
localFruit = grapeRepository.findByIdAndCountryId(id, countryId);
break;
default:
/* throwing UnrecognizedFruitException */
}
关于SO还有其他几个类似的问题,但到目前为止还没有答案/解决方案 - 例如