Spring 4 @Configuration命令用于设置JPA

时间:2017-04-07 14:18:21

标签: java spring hibernate jpa jersey-2.0

我在Spring 4中有一个工作的Jersey 2.2 applisaction,其中我使用Eclipselink作为JPA实现。

应用程序配置calss如下所示:

@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);
}
}

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

现在,这很有效。在启动时,应用程序配置类正在加载FIRST所以&#34; PropertySourcesPlaceholderConfigurer&#34;得到注册,我可以在jpa配置类中使用@Value(...)注释,它被加载为SECOND。

今天我已经决定用Hibernate代替Eclipselink,因为它有审计能力。

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

并将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("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;
}
}

现在,令我惊讶的是,应用程序配置和jpa配置类的加载/执行顺序已交换,因此jpa配置正在加载FIRST然后应用程序配置SECONDLY导致&#34; PropertySourcesPlaceholderConfigurer&#34;没有在jpa配置类加载时注册,所以@value注释不起作用!

我真的很想知道为什么会这样?为什么要交换执行顺序?

我知道我可以通过不将jpa config calass声明为@Configuration并在应用程序配置类中将其注册为bean来欺骗它,如:

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

但是,我想知道,这里发生了什么?

1 个答案:

答案 0 :(得分:0)

订单更改的原因是将PersistenceExceptionTranslationPostProcessor bean引入JPAConfig类。

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

将其移至VedicaConfig类可以解决我的问题。