【问题标题】:Ignore some classes while scanning PackagesToScan扫描 PackagesToScan 时忽略某些类
【发布时间】:2013-04-23 23:48:57
【问题描述】:

我有一个包(比如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 中的某些课程?

【问题讨论】:

  • 您可以删除/评论 @Entity 注释,直到您的实体完成。比持久性提供者不会拾取它。
  • 难道不能只扫描一些我想测试的特定实体吗?
  • 您还可以删除 packagesToScan 选项,创建 persistence.xml 并在此处列出实体。我仍然不明白您排除某些实体的动机 - 如果您处于开发过程中并且您的实体不完整,或者我遗漏了什么,您可以轻松删除 @Entity 注释?
  • 你有没有找到一个解决方案来忽略packagestoscan中的一些实体?
  • @nilgun 不,我没有。

标签: spring spring-data spring-data-jpa applicationcontext


【解决方案1】:

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

<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>

我意识到LocalSessionFactoryBean 类上有一个setEntityTypeFilters function,可用于过滤要包含的类。在这个例子中,我使用了RegexPatternTypeFilter,但也有other types of filters

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

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

【讨论】:

    【解决方案2】:

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

    // 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");
            }
        });
    

    【讨论】:

      【解决方案3】:

      我找到了使用setPackagesToScan 然后删除不需要的包的解决方案。事实证明,PersistenceUnitPostProcessor 中的persistenceUnit.getManagedClassNames() 返回一个可以操作的常规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"
      )
      

      【讨论】:

        【解决方案4】:

        我还使用 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;
        }
        

        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-07-10
          • 1970-01-01
          • 2021-10-31
          • 2018-07-01
          • 2016-09-21
          • 1970-01-01
          • 2017-04-05
          相关资源
          最近更新 更多