Spring Boot voodoo需要使用DataNucleus和Hikari

时间:2017-06-01 10:46:03

标签: spring jpa spring-boot spring-data-jpa datanucleus

欢迎使用此配置工作的任何帮助。

我正在尝试从Spring Boot接管自动连接池,数据源和JPA配置,以允许我将DataNucleus带入混合而不是Hibernate

我的方法是编写代码Boot,说明在试错的基础上缺失。我不得不删除Hibernate依赖项以允许DataNucleus运行。

也许我现在编码太多了,也许不是我不够远。

春天因错误而崩溃:

Exception encountered during context initialization - cancelling refresh attempt: 
[huge SNIP]
nested exception is org.springframework.beans.BeanInstantiationException: 
    Failed to instantiate [org.springframework.data.repository.support.Repositories]: 
    Factory method 'repositories' threw exception; 
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
    Error creating bean with name 'symbolRepositoryImpl': 
    Unsatisfied dependency expressed through field 'entityManager'; 
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
    No qualifying bean of type 'javax.persistence.EntityManager' available: 
    expected single matching bean but found 2:
    org.springframework.orm.jpa.SharedEntityManagerCreator#0,
    org.springframework.orm.jpa.SharedEntityManagerCreator#1
[SNIP]
2017-06-01 09:43:09.675 ERROR 9108 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field entityManager in com.bp.gis.tardis.repository.SymbolRepositoryImpl 
    required a single bean, but 2 were found:
    - org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
    - org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, 
or using @Qualifier to identify the bean that should be consumed

我可能花费数小时进一步调试这个,但是断点来自其中一个应该注入了entityManager的存储库的初始化。

这是我手动实例化的内容:

@Configuration
@EnableJpaRepositories(
        basePackages = {"org.adam.repository"}
)
public class DataSourceConfig {


    @Bean
    @ConfigurationProperties(prefix = "adam.datasource")
    public AdamDataSourceProperties getDataSourceProperties() {
        return new AdamDataSourceProperties();
    }

    @Bean
    public DataSource getDataSource() {
        AdamDataSourceProperties props = getDataSourceProperties();
        return new HikariDataSource(props.getHikariConfig());
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean getEmfBean() {
        LocalContainerEntityManagerFactoryBean emfBean =
                new LocalContainerEntityManagerFactoryBean();
        emfBean.setDataSource(getDataSource());
        emfBean.setPersistenceUnitName("adam");
        return emfBean;
    }

    @Bean
    public EntityManagerFactory getEmf() {
        LocalContainerEntityManagerFactoryBean emfBean = getEmfBean();
        return emfBean.getNativeEntityManagerFactory();
    }

}

我的AdamDatasourceProperties由Spring初始化,使用application.properties中的“adam.datasource”前缀值,然后可以创建一个HikariConfig对象来实例化HikariDataSource }。这一点实际上很好,它是实体经理工厂可能导致问题 - 或其他。

我没有证据证明我的上一个方法getEmf()实际上是在帮助。

另外,我怀疑错误

  

需要一个bean,但找到了2个

或建议的操作很有帮助 - 我不想进入Spring源代码,以便在Spring的SharedEntityManagerCreator上注释其中一个方法为@Primary

更新 如果在类路径上找到其他JPA API类,则DataNucleus将无法运行 - 它坚持使用自己的持久性API版本 - 因此必须删除Hibernate包。

Caused by: org.datanucleus.exceptions.NucleusUserException: 
    Found Meta-Data for class org.adam.entity.TimeSeriesEntity 
    but this class is either not enhanced or you have multiple copies 
    of the persistence API jar in your CLASSPATH!! 
    Make sure all persistable classes are enhanced before running 
    DataNucleus and/or the CLASSPATH is correct.
    at org.datanucleus.metadata.MetaDataManagerImpl
             .initialiseClassMetaData(MetaDataManagerImpl.java:2814)

所以我从spring-boot-starter-data-jpa中排除了Hibernate并且错误消失了。

1 个答案:

答案 0 :(得分:1)

我将LocalContainerEntityManagerFactoryBean方法名称更改为entityManagerFactory

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean emfBean =
            new LocalContainerEntityManagerFactoryBean();
    emfBean.setDataSource(getDataSource());
    emfBean.setPersistenceUnitName("adam");
    return emfBean;
}

要启用测试,我必须复制此@Configuration类并更改EMF方法以接受Spring的测试数据库:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
        @Qualifier("dataSource") DataSource dataSource) {
    LocalContainerEntityManagerFactoryBean emfBean =
            new LocalContainerEntityManagerFactoryBean();
    emfBean.setDataSource(dataSource);
    emfBean.setPersistenceUnitName("adam");
    return emfBean;
}

@Qualifier是为了Intellij的缘故,他的Spring facet在这里抱怨了2名注射候选人。

我还发现,使用此配置,EntityManager的存储库/ DTO依赖项注入不适用于@Autowired。它必须是原生JPA注释:

@PersistenceContext
private EntityManager entityManager;

使用我以前的Hibernate和OpenJPA配置,Spring很乐意在EntityManager出现时注入自己实例化的@Autowire

这为我的牛肉添加了更多的燃料。它经常不会像锡上所说的那样做。 Spring测试应该在包层次结构中找到@Configuration类,但不是 - 我需要使用@Import。 Spring也应该根据类型(EntityManagerDataSource等)找到依赖注入候选者,但它不会 - 在某些情况下,它们必须由名为特定名称或{{1}的方法生成注释声明一个名称。

不过,已经完成了。