2017-02-09 4 views
14

У нас есть базовый класс репозитория JPA с некоторыми дополнительными утилитами, которые мы используем в наших проектах. После Spring Data JPA documentation мы создали класс и использовать @EnableJpaRepositories аннотаций в классе конфигурации, как в следующем примере:Есть ли способ зарегистрировать базовый класс репозитория с автоматической настройкой пружинной загрузки?

@Configuration 
@EnableJpaRepositories(basePackageClasses = MyApplication.class, 
    repositoryBaseClass = MyJpaRepositoryImpl.class) 
public class SpringDataJpaMyRepositoryConfiguration { 
} 

Мы также установить basePackageClasses атрибут, чтобы наши хранилища найдены, как класс конфигурация не является в корневом пакете приложения. Все работает так, как ожидалось, поэтому проблем пока нет.

Теперь мы хотели бы создать стартер загрузки весны, чтобы добавить базовый класс репозитория к нашим проектам без дальнейшей настройки, но мы не знаем, как это сделать. Если мы создадим класс AutoConfiguration с EnableJpaRepositories установка repositoryBaseClass атрибута, автоматическое хранилищем стратегии поиска, которая ищет хранилища под классом с аннотацией @SpringBootApplication аннотаций больше не работают.

И мы не можем использовать атрибут basePackageClasses, так как мы не знаем основной класс или пакет проекта с использованием автоконфигурации.

Есть ли способ сделать это? Может быть, переопределив некоторые компоненты в нашей автоконфигурации?

Идеальный способ - это то, что позволяет установить базовый класс репозитория без необходимости повторного определения всей автоконфигурации JPA Spring Data.

+0

Я Хавин g той же проблемой и все еще ищет решение. Ответы, предоставленные rdlopes и dan.jones, к сожалению, не решают проблему. –

ответ

1

EDIT: Я довольно много переписывается мой ответ - я не понял оригинальный вопрос

Это не приятное решение, но единственный способ, я могу видеть эту работу является использование SPEL внутри @EnableJpaRepositories.

Это может затем перейти в вашем авто-конфигурации и использовать @ConditionalOnProperty только автоматическую настройку, если свойство базового пакета устанавливается

@Configuration 
@ConditionalOnProperty("repositories-base-packages") 
public class BaseRepositoryAutoConfiguration { 

    @Configuration 
    @EnableJpaRepositories(
      repositoryBaseClass = MyJpaRepositoryImpl.class, 
      basePackages = "${repositories-base-packages}" 
    ) 
    public static class JpaRepositoriesConfig { } 

} 

Затем убедитесь, что у вас есть application.properties или application.yml, который определяет repositories-base-packages внутри вашего приложения ,

Не знаете, как бы вы объявили несколько базовых пакетов, мое знание SpEL является примитивным, поэтому не уверен, что это будет возможно.

+0

Спасибо за ваш ответ, но это не решит нашу проблему. Ваша конфигурация устанавливает пакеты для поиска классов с аннотациями JPA, но наша проблема основана на поиске репозиториев Spring Data JPA, которые не совпадают. Кроме того, я ищу решение, которое не требует дальнейшей настройки, будь то класс конфигурации или свойство. В противном случае наш текущий класс конфигурации достаточно прост. –

+0

Извините, но я не понял этот вопрос. Я обновил ответ другим решением. Это работает, но не уверен, что можно объявить несколько базовых пакетов, кому-то с более SpEL придется комментировать –

+0

Еще раз спасибо, но мы ищем решение, которое не требует дальнейшей настройки, даже не свойства конфигурации. Мы хотели бы установить базовый класс репозитория и сохранить автоконфигурацию по умолчанию, предоставленную стартером загрузки весны для данных весны jpa, или, по крайней мере, обеспечить тот же уровень автоконфигурации. –

1

Этот вопрос заставлял меня сходить с ума в то время, поэтому я думал, что смогу помочь вам в этом.

В принципе, идея заключается в следующем:

  • Создать класс конфигурации для JPA конфигурации
  • Добавить @EntityScan и @EnableJpaRepositories ссылающегося тот же класс конфигурации как basePackageClass
  • импортировать эту конфигурацию класса в ваша автоконфигурация
  • Создайте аннотацию, которую вы можете повторно использовать там, где вам нужен ваш конфигуратор Jpa

В вашем примере вы используете свой класс приложений Spring в качестве базы для сканирования.

Я смирился проект образца для POC основных идей в https://github.com/rdlopes/custom-jpa-demo

В примере, есть проект для JPA сущностей/хранилищ обнажая конфигурацию JPA:

@Configuration 
    @EntityScan(basePackageClasses = JpaConfiguration.class) 
    @EnableJpaRepositories(basePackageClasses = JpaConfiguration.class, 
          repositoryBaseClass = BaseRepositoryImpl.class) 
    public class JpaConfiguration { 

    } 

Будьте осторожны с общей реализацией для хранилищ, вам нужно показать особую подпись:

@NoRepositoryBean 
public class BaseRepositoryImpl<T, ID extends Serializable> 
     extends SimpleJpaRepository<T, ID> 
     implements BaseRepository<T, ID> { 

    public BaseRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) { 
     super(entityInformation, entityManager); 
    } 

    @Override 
    public String someCustomMethod(ID id) { 
     return "Class for entity of id " + id + " is: " + getDomainClass().getSimpleName(); 
    } 
} 

вы можете создать автоматическую конфигурацию, как с Уче:

@Configuration 
@ConditionalOnClass(CustomJpaRepositories.class) 
@Import(JpaConfiguration.class) 
public class JpaCustomAutoConfiguration { 

} 

Обеспечение аннотации, чтобы держать вещи аккуратно и использовать его там, где вам нужно JPA:

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Inherited 
public @interface CustomJpaRepositories { 
} 

Используя классы JPA будет столь же просто, как это аннотация, где вы называете JPA репозитории:

@SpringBootApplication 
@CustomJpaRepositories 
public class CustomJpaSampleApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(CustomJpaSampleApplication.class, args); 
    } 

    @Bean 
    public CommandLineRunner dataInitializer(UserRepository userRepository) { 
     return args -> { 
      User user1 = new User(); 
      user1.setName("user 1"); 
      userRepository.save(user1); 

      User user2 = new User(); 
      user2.setName("user 2"); 
      userRepository.save(user2); 

      userRepository.findAll() 
          .forEach(user -> System.out.println(
            userRepository.someCustomMethod(user.getId()))); 
     }; 
    } 
} 

Надеется, что это поможет вам получать прошло голова чешут моменты :-)

+0

Спасибо Rui за информацию и образец проекта. Однако это не то, что нам действительно нужно решить. Мы не предоставляем сущности и репозитории в библиотеке, которая предоставляет базовый класс репозитория, который должен быть включен в каждый проект. Но вы можете легко воспроизвести наш сценарий в своем примере проекта, просто переместите объект _User_ и _UserRepository_ из модуля _custom-jpa_ в модуль _custom-jpa-demo_. Вы решили эту ситуацию случайно? –

+0

Пока неясно, что вы можете и что вы не можете изменить.Например, можно предположить, что вы вводите свои утилиты в пользовательский репозиторий путем автоподготовки. Вы также можете использовать другую конфигурацию @Configuration в своей автоконфигурации, чтобы ссылаться на другой набор компонентов и использовать шаблон композиции. Проблема в том, что у нас нет четкой архитектуры для вашей проблемы, я думаю, именно поэтому другой ответ не соответствует вашим требованиям. – rdlopes

+0

Буду рад ответить на любые сомнения или добавить дополнительную информацию. Другой ответ почти на пути, единственная проблема заключается в том, что он не решает требования не нуждаться в дальнейшей настройке в приложении. И это требование - это то, что трудно решить, я думаю. –

Смежные вопросы