Ao usar @EntityScan
todas as entidades no basePackages especificado, elas são selecionadas pelo scan. Por certos motivos , gostaríamos de evitar isso.
Tivemos a ideia de substituir a @EntityScan
anotação pela configuração manual para incluir apenas classes de entidade específicas, em vez de todas as entidades do pacote, chamando factoryBean.setManagedTypes(managedTypes)
.
Há uma postagem de baeldung que vai nessa direção, mas o foco não está na configuração de managedTypes únicos.
Na verdade, ficamos surpresos por não termos encontrado nenhuma postagem de blog, pergunta do stackoverflow, etc. que tratasse da questão "É possível configurar o @EntityScan ou uma alternativa para rastrear apenas classes únicas, não pacotes completos?".
Há algum problema ou desvantagem em fazer isso em um aplicativo Spring Boot?
O javadoc de LocalContainerEntityManagerFactoryBean.setManagedTypes
even diz:
Defina o PersistenceManagedTypes a ser usado para criar a lista de tipos gerenciados como uma alternativa à varredura de entidades. -- https://docs.spring.io...orm/jpa/LocalContainerEntityManagerFactoryBean
Criei um projeto de exemplo para demonstrar a ideia: https://github.com/frankkriegl-zero/jpa-managed-types-sample/tree/stackoverflow-question-79541611
Da classe de configuração JpaConfig :
@Configuration
public class JpaConfig {
List<String> sharedManagedEntityClassNames = Stream.of(
external.model.Book.class // located in a 'remote' package, outside of org.example.bookstore
).map(Class::getName).toList();
List<String> managedEntityPackages = List.of(
"org.example.bookstore.model"
);
@Bean(name = "persistenceManagedTypes")
PersistenceManagedTypes persistenceManagedTypes(ResourceLoader resourceLoader) {
var scanResult = new PersistenceManagedTypesScanner(resourceLoader)
.scan(managedEntityPackages.toArray(new String[0]));
// merge the shared managed entity class names with the scanned ones
List<String> managedClassNames = new ArrayList<>();
managedClassNames.addAll(sharedManagedEntityClassNames);
managedClassNames.addAll(scanResult.getManagedClassNames());
return PersistenceManagedTypes.of(managedClassNames, Collections.emptyList());
}
// entityManagerFactoryBean
}
É assim que substituímos o bean entityManagerFactory:
@Bean(name = "entityManagerFactory")
public EntityManagerFactory entityManagerFactory(DataSource dataSource,
PersistenceManagedTypes managedTypes) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setManagedTypes(managedTypes); // alternative to @EntityScan and @EnableJpaRepositories
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
Não nos sentimos muito confiantes em criar nosso próprio bean emFactory, pois este é a espinha dorsal de toda lógica relacionada ao JPA em um aplicativo baseado em JPA:
- Não temos certeza se isso poderia criar um esforço de manutenção adicional caso as implementações do framework (Spring Boot ou Hibernate) mudassem aqui.
- Como esse é um componente crítico com configurações bastante complexas, temos um certo medo de ignorar algo e quebrar a camada de persistência do aplicativo.
Algum conselho ou experiência com o uso setManagedTypes(PersistenceManagedTypes)
em vez de @EntityScan
?
Obrigado!