Spring Data - 一个处理实体常见操作的服务类(如何自动装配JpaRepository)

时间:2016-07-12 19:00:57

标签: java generics spring-data spring-data-jpa

主要问题 - 我想编写一个服务(比如说CommonService)来处理一系列实体的查找,计数等常见操作(有一个原因我无法使用JpaRepository - 盒子方法,如下所述)。我如何自动装配JpaRepository来实现这一目标?详情 -

并发症 - 现在,由于业务需求,我必须将国家/地区ID与每个实体相关联(保存时使用,并在检索时使用等)。我从登录用户那里得到这个ID(即不作为保存或查询实体的一部分提供) - 所以我不能直接使用(或通过REST公开)JpaRepository save或findOne - 我必须通过一个服务来执行此操作然后使用JpaRepository保存/提取。

技术堆栈

  1. Spring data jpa 1.9.4
  2. Spring boot 1.3.5
  3. JPA提供程序hibernate
  4. DB - MySQL
  5. 我有一个抽象的基本实体 - 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还有其他几个类似的问题,但到目前为止还没有答案/解决方案 - 例如

    1. Spring data: Autowire JpaRepository (Generic type)
    2. how to save simple CRUD codes in a service, just like GenericDao/JpaRepository?
    3. 感谢您的帮助!

0 个答案:

没有答案