Модуляризация конфигурации Spring Data JPA - PullRequest
0 голосов
/ 13 мая 2019

Мы ищем способ для разных модулей отдельно указывать @ComponentScan, @EnableJpaRepositories и EntityManagerFactory.setPackagesToScan.

Мы объединяем несколько модулей кода в наше веб-приложение. Кроме того, мы допускаем специфичные для клиента расширения базового кода, которые могут добавлять дополнительные пакеты. В ходе тестирования я обнаружил, что могу добавить дополнительный класс конфигурации java, и дополнительные пакеты в @ComponentScan и @EnableJpaRepositories подобраны. Я думаю, что если бы я мог использовать @EntityScan, я бы увидел подобное поведение.

Однако мы выполняем некоторые настройки в EntityManagerFactory, поэтому @EntityScan больше не является опцией. Я не думаю, что мы хотим указать другой EntityManagerFactory для каждого модуля. Метод setPacakgesToScan выполняет замену пакетов (вместо добавления в текущий список).

Было много сообщений о возможности проблемной установки пакетов ToScan, но это значительно увеличивает сложность.

Пример базового класса конфигурации

@Configuration
@EnableJpaRepositories(basePackages = { 
        "a", "b", "c"
 }
,repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class
)
@ComponentScan(basePackages = {
        "a", "b", "c"
}
)
public class BaseConfig {       
    @Bean
    public EntityManagerFactory entityManagerFactory() throws NamingException {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJtaDataSource(dataSource());
        emf.setPackagesToScan(new String[] {"a", "b", "c"})
    }
}

Пример класса конфигурации расширения

@Configuration
@EnableJpaRepositories(basePackages = { 
        "d"
 }
,repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class
)
@ComponentScan(basePackages = {
        "d"
}
)
public class ExtensionConfig {      
    @Bean
    public EntityManagerFactory entityManagerFactory() throws NamingException {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJtaDataSource(dataSource());
        emf.setPackagesToScan(new String[] {"d"})
    }
}

Есть ли другой способ добиться такого поведения?

Спасибо.

1 Ответ

1 голос
/ 13 мая 2019

Вы можете попробовать следующий подход, хотя я не уверен, что он лучший:

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

public class EmfPackages {
    private final String[] packages;
    public EmfPackages(String[] packages) {
        this.packages = packages;
    }
    public String[] getPackages() {
        return this.packages;
    }
}

Затем настройте оба класса конфигурации:

public class BaseConfig {       
    @Bean
    public EMFPackages baseEmfPackages() {
        return new EmfPackages(new String[] {"a", "b", "c"});
    }    

    @Bean
    // both "holders" are now injected here
    // AFAIK this feature works in Spring 4+
    public EntityManagerFactory entityManagerFactory(List<EmfPackages> emfPackages) throws NamingException { 
        // actually this is Java 8+ style, adjust for lower versions if needed
        final String[] combinedPackages = emfPackages.stream()
            .flatMap(p -> Arrays.stream(p.getPackages()))
            .collect(Collectors.toList())
            .toArray(new String[0]{});

        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJtaDataSource(dataSource());
        emf.setPackagesToScan(combinedPackages)
    }    
}

public class ExtensionConfig {      
    @Bean
    public EmfPackages extendedEmfPackages() {
        return new EmfPackages(new String[] {"d"});
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...