如何过滤 LocalContainerEntityManagerFactoryBean 扫描的实体?

Raf*_*Ch. 5 java spring jpa spring-data spring-data-jpa

我使用 Spring Boot、Spring Data JPA 和 Hibernate。

我需要过滤EntityManager由自定义注释管理的实体。LocalContainerEntityManagerFactoryBean允许设置被扫描的包列表,但过滤器似乎是硬编码在DefaultPersistenceUnitManager.

否则LocalSessionFactoryBuilder(特定于 Hibernate 的)具有此功能(方法setEntityTypeFilters),但不能与需要EntityManagerFactory.

如何将实体过滤应用于LocalContainerEntityManagerFactoryBean

小智 5

我遇到了类似的问题:我想“排除”一些实体,同时仍然使用LocalContainerEntityManagerFactoryBean. 就我而言,我想利用@Profile(...)spring 使用的注释,因为仅当特定配置文件处于活动状态时我才需要某些实体。我通过实现PersistenceUnitPostProcessor删除扫描仪添加的类来解决这个问题。它可能不是最优雅的解决方案,但它有效(Spring 4.1.2)。

public class ProfileAwarePersistenceUnitPostProcessor implements PersistenceUnitPostProcessor {

    @Autowired
    Environment environment;

    /**
     * Post process the persistence unit and remove Entity classes that require a specific spring profile
     * if profile is not active.
     * 
     * @param pui The persistence unit that was put together so far.
     * @see org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor#postProcessPersistenceUnitInfo(org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo)
     */
    @Override
    public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
        // Check for null to be sure.
        if (pui.getManagedClassNames() != null) {
            Iterator<String> iterator = pui.getManagedClassNames().iterator();
            while (iterator.hasNext()) {
                String className = iterator.next();
                try {
                    Class<?> entityClass = Class.forName(className);
                    Profile profileAnnotation = entityClass.getAnnotation(Profile.class);
                    if (profileAnnotation != null) {
                        String[] requiredProfiles = profileAnnotation.value();
                        if (!environment.acceptsProfiles(requiredProfiles)) {
                            Logging.debug("Removing class " + className + " from persistence unit since none of the required profiles is active "
                                    + StringUtils.join(", ", requiredProfiles));
                            iterator.remove();
                        }
                    }
                } catch (ClassNotFoundException e) {
                    // Something must have gone wrong during scanning if class is suddenly not found anymore.
                    Logging.warn("Class " + className + " not found  while post processing persistence unit.", e);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

可以使用任何其他注释来代替 Profile。


Oli*_*ohm 0

使用Spring Boot,只需按照参考文档@EntityScan中的描述使用即可。

\n\n

如果 \xe2\x80\x93 正如此问题 \xe2\x80\x93 的评论中所表达的那样,您需要使用多个数据源,请查看Spring Data 示例存储库中的相应项目

\n

  • `@EntityScan` 不支持自定义过滤(仅包名称)。我还需要两个数据库的两个独立的实体管理器工厂。这就是为什么我想显式配置 `LocalContainerEntityManagerFactoryBean`。 (3认同)