简体   繁体   English

Spring 4 @Configuration设置JPA的命令

[英]Spring 4 @Configuration order for setting up JPA

I had a working Jersey 2.2 applisaction with Spring 4 in which I was using Eclipselink as JPA implementation. 我在Spring 4上具有有效的Jersey 2.2应用程序,其中使用Eclipselink作为JPA实现。

The application config calss looks as follows: 应用程序的配置如下所示:

@Configuration
@ComponentScan(value = "com.nws.vedica", lazyInit = true)
@PropertySource({"classpath:swagger.properties", "classpath:vedica.properties"})
@ApplicationPath("/api")

public class VedicaConfig extends ResourceConfig {

public VedicaConfig() {
    packages("com.nws.vedica");
    property(ServletProperties.FILTER_FORWARD_ON_404, true);
    register(MultiPartFeature.class);
    register(JacksonFeature.class);
    register(ValidationFeature.class);
    register(ValidationConfigurationContextResolver.class);
    register(PropertySourcesPlaceholderConfigurer.class);

    register(ApiListingResource.class);
    register(SwaggerSerializers.class);
}
}

The JPA configuration class: JPA配置类:

@Configuration
@EnableTransactionManagement
public class JPAConfig {

private Map<String, String> properties;

@Value("${db.url}")
private String dbConnectionURL;

@Value("${db.user}")
private String dbUser;

@Value("${db.pass}")
private String dbPassword;

@PostConstruct
public void init() {
    properties = new HashMap<>();
    properties.put("javax.persistence.jdbc.url", dbConnectionURL);
    properties.put("javax.persistence.jdbc.user", dbUser);
    properties.put("javax.persistence.jdbc.password", dbPassword);
    properties.put("javax.persistence.jdbc.driver", "org.postgresql.Driver");
    properties.put("javax.persistence.target-database", "PostgreSQL");
    properties.put("eclipselink.cache.shared.default", "true");
    properties.put("eclipselink.ddl-generation", "none");
    properties.put("eclipselink.logging.level.sql", "fine");
    properties.put("eclipselink.logging.parameters", "true");
    properties.put("eclipselink.deploy-on-startup", "true");
    properties.put("eclipselink.ddl-generation.output-mode", "database");
}

@Bean
public JpaTransactionManager jpaTransMan(){
    JpaTransactionManager jtManager = new JpaTransactionManager(
            getEntityManagerFactoryBean().getObject());
    return jtManager;
}

@Bean
public LocalEntityManagerFactoryBean getEntityManagerFactoryBean() {
    LocalEntityManagerFactoryBean lemfb = new LocalEntityManagerFactoryBean();
    lemfb.setJpaPropertyMap(properties);
    lemfb.setPersistenceUnitName(Vedantas.PU_NAME);
    lemfb.setPersistenceProviderClass(org.eclipse.persistence.jpa.PersistenceProvider.class);
    return lemfb;
}
}

Now, this works well. 现在,这很好。 On startup, application config class is being loaded FIRST so "PropertySourcesPlaceholderConfigurer" gets registered and I can use @Value(...) annotations in jpa config class which gets loaded as SECOND. 启动时,将首先加载应用程序配置类,以便注册“ PropertySourcesPlaceholderConfigurer”,并且我可以在jpa配置类中使用@Value(...)批注,该批注将作为SECOND加载。

Today I have decided that I'll replace Eclipselink with Hibernate because of it's auditing abilities. 今天,我已经决定将Hibernate替换为Eclipselink,因为它具有审核功能。

To pom.xml I have added: 我在pom.xml中添加了:

<dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.2.9.Final</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.0.Final</version>
    </dependency>


    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-envers</artifactId>
        <version>5.2.9.Final</version>
    </dependency>

and have changed jpa config class to: 并将jpa config类更改为:

@Configuration
@EnableTransactionManagement
public class JPAConfig {

private Map<String, String> properties;

@Value("${db.url}")
private String dbConnectionURL;

@Value("${db.user}")
private String dbUser;

@Value("${db.pass}")
private String dbPassword;

@PostConstruct
public void init() {
    properties = new HashMap<>();
    properties.put("javax.persistence.jdbc.url", dbConnectionURL);
    properties.put("javax.persistence.jdbc.user", dbUser);
    properties.put("javax.persistence.jdbc.password", dbPassword);
    properties.put("javax.persistence.jdbc.driver", "org.postgresql.Driver");
    properties.put("javax.persistence.target-database", "PostgreSQL");
    properties.put("hibernate.hbm2ddl.auto", "create");
    properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);

    return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
    return new PersistenceExceptionTranslationPostProcessor();
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setPackagesToScan(new String[]{"com.nws.vedica.model"});
    em.setPersistenceUnitName(Vedantas.PU_NAME);

    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    em.setJpaPropertyMap(properties);

    return em;
}
}

Now, to my surprise, load/execution order of application config and jpa config classes has swapped so jpa config is being loaded FIRST and then application config SECONDLY which causes "PropertySourcesPlaceholderConfigurer" not being registered at jpa config class load time, so @value annotations are not working! 现在,令我惊讶的是,应用程序配置和jpa config类的加载/执行顺序已互换,因此先加载jpa config,然后第二次进行应用程序配置,这会导致在jpa config类加载时未注册“ PropertySourcesPlaceholderConfigurer”,因此@value注释不工作!

I am really interested in knowing why is that so? 我真的很想知道为什么会这样? Why has the execution order swapped? 为什么要交换执行顺序?

I know I can trick it by not declaring jpa config calass as @Configuration and just register it as a bean in application config class like: 我知道我可以通过不将jpa config calass声明为@Configuration来欺骗它,而只是将其注册为bean,例如:

    @Bean
    public JPAConfig setUpJpaHibernate() {
        return new JPAConfig();
    }

But still, I would like to know, what is happening here? 但是,我想知道,这里正在发生什么?

the reason that the order changed was introduction of PersistenceExceptionTranslationPostProcessor bean into JPAConfig class. 顺序更改的原因是在JPAConfig类中引入了PersistenceExceptionTranslationPostProcessor bean。

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
    return new PersistenceExceptionTranslationPostProcessor();
}

Moving this to the VedicaConfig class solves the problem for me. 将其移至VedicaConfig类可以为我解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM