我在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();
}
但是,我想知道,这里发生了什么?
答案 0 :(得分:0)
订单更改的原因是将PersistenceExceptionTranslationPostProcessor
bean引入JPAConfig类。
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
将其移至VedicaConfig类可以解决我的问题。