16

我有一个包(比如说packagesToScan),其中包含我希望保留的类,并用@Entity.

在定义ApplicationContext配置时,我做了如下。


@Configuration
@EnableJpaRepositories("packagesToScan")
@EnableTransactionManagement
@PropertySource("server/jdbc.properties")
@ComponentScan("packagesToScan")

public class JpaContext {

... // Other configurations ....

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    emf.setDataSource(this.dataSource());
    emf.setJpaVendorAdapter(this.jpaVendorAdapter());
    emf.setPackagesToScan("packagesToScan");
    emf.setJpaProperties(this.hibernateProperties());
    return emf;

 }

在开发过程中,我有一些类packagesToScan不满足持久性要求(例如没有主键等),因此由于ApplicationContext设置失败,我不允许运行测试。

现在, 有什么方法可以只扫描一些选定的课程或忽略其中的一些课程packagesToScan

4

4 回答 4

9

我一直在尝试解决同样的问题,最终得到了如下解决方案:

<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan" value="com.mycompany.bean"/>
    <property name="entityTypeFilters" ref="packagesToScanIncludeRegexPattern">
    </property>
    <property name="hibernateProperties">
        // ...
    </property>
</bean>

<bean id="packagesToScanIncludeRegexPattern" class="org.springframework.core.type.filter.RegexPatternTypeFilter" >
    <constructor-arg index="0" value="^(?!com.mycompany.bean.Test).*"/>
</bean>

我意识到类上有一个函数setEntityTypeFilters可以LocalSessionFactoryBean用来过滤要包含的类。在此示例中,我使用了 RegexPatternTypeFilter,但也有其他类型的过滤器

另请注意,过滤器与包含语义一起使用。为了转换为排除语义,我不得不在正则表达式中使用负前瞻。

此示例显示了 xml 配置,但转换为基于 java 的配置应该很简单。

于 2015-11-23T20:50:55.550 回答
6

我偶然发现了一个类似的问题。我需要从包中添加一些但不是所有实体。这是我的做法:

// add all entities from some package
localContainerEntityManagerFactoryBean.setPackagesToScan("com.companyname.model");
// add only required enitites from a libray
localContainerEntityManagerFactoryBean.setPersistenceUnitPostProcessors(new PersistenceUnitPostProcessor() {
        @Override
        public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo persistenceUnit) {
            persistenceUnit.addManagedClassName("com.companyname.common.model.SomeEntityName");
        }
    });
于 2016-12-01T11:41:59.443 回答
1

我找到了一个使用setPackagesToScan然后删除不需要的包的解决方案。事实证明,persistenceUnit.getManagedClassNames()inPersistenceUnitPostProcessor返回一个ArrayList可以操作的正则。

em.setPersistenceUnitPostProcessors(new PersistenceUnitPostProcessor() {
    @Override
    public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo persistenceUnit) {
        List<String> managedClassNames = persistenceUnit.getManagedClassNames();
        managedClassNames.removeIf(fullClassName -> fullClassName.startsWith("com.example.twodatasources.product"));
    }
});

在我的情况下,显示的persistanceUnit 负责所有实体,但com.example.twodatasources.product包中的实体除外。对方只负责com.example.twodatasources.product

上面的代码用于休眠部分。值得一提的是,弹簧部分也应该进行过滤。这可以通过添加 ComponentScan.Filter 来实现,@EnableJpaRepositories如下所示:

@Configuration
@PropertySource({ "classpath:application.yml" })
@EnableJpaRepositories(
    basePackages = "com.example.twodatasources",
    excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = "com\\.example\\.twodatasources\\.product\\..*")},
    entityManagerFactoryRef = "userEntityManager",
    transactionManagerRef = "userTransactionManager"
)
于 2021-11-29T20:26:08.617 回答
0

我还使用 entityTypeFilters 在扫描 PackagesToScan 时忽略了一些类

但正如我发现通过设置 entityTypeFilters

<property name="entityTypeFilters" ref="packagesToScanIncludeRegexPattern">

清除现有的默认过滤器(根据文档):

为基于 Spring 的实体类扫描指定自定义类型过滤器。默认是在所有指定的包中搜索带有 @javax.persistence.Entity、@javax.persistence.Embeddable 或 @javax.persistence.MappedSuperclass 注释的类。

当我在调试中检查时,这导致所有类包都被 spring 扫描,它们匹配 packagesToScan 条件,除了 packagesToScanIncludeRegexPattern 正则表达式。这对启动时间有影响。

作为解决方法,我使用过滤器实现了自定义过滤器,默认情况下是 puls regexp 过滤器:

public class RegexPatternEntitiesTypeFilter extends AbstractClassTestingTypeFilter {

private final Set<String> entityPackageRegistry;
private final Pattern pattern = Pattern.compile("^(?!my.company.package.exclude).*");

public RegexPatternEntitiesTypeFilter() {
    entityPackageRegistry = ImmutableSet.of(Entity.class.getName(), Embeddable.class.getName(),
        MappedSuperclass.class.getName());
}

@Override
protected boolean match(ClassMetadata metadata) {
    boolean result = true;
    if (metadata instanceof AnnotationMetadataReadingVisitor) {
        Set<String> annotationTypes = ((AnnotationMetadataReadingVisitor) metadata).getAnnotationTypes();
        result = !Sets.intersection(entityPackageRegistry, annotationTypes).isEmpty();
    }
    boolean matches = this.pattern.matcher(metadata.getClassName()).matches();
    return result && matches;
}

}

于 2021-10-07T09:12:34.563 回答