J'ai commencé le développement d'une nouvelle application Spring 3.2.4 et j'essaie d'utiliser Java au lieu des fichiers XML comme je l'ai utilisé dans le passé. Cependant, j'ai du mal à faire le transition.
En utilisant XML, je le coderais comme suit:
<!-- application datasource -->
<bean id="dataSource.jndi" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton" lazy-init="true">
<property name="jndiName" value="Java:comp/env/jdbc/liment" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource.jndi"/>
</bean>
Cependant, je suis vraiment coincé à essayer de comprendre comment faire cela en Java. J'essaie de répliquer la configuration, mais j'ai des problèmes:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages={"com.ia"})
public class AppConfigJPA {
@Bean
public DataSource dataSource() {
// configure and return the necessary JDBC DataSource
JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean();
dataSource.setJndiName("Java:comp/env/jdbc/liment");
try {
dataSource.afterPropertiesSet();
} catch (IllegalArgumentException | NamingException e) {
// rethrow
throw new RuntimeException(e);
}
return (DataSource)dataSource.getObject();
}
@Bean
public EntityManagerFactory entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceUnitName("persistenceUnit");
emf.setDataSource(dataSource());
emf.afterPropertiesSet
return emf.getObject();
}
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
}
Cependant, j'obtiens le message d'erreur suivant:
Caused by: Java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.Java:142)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.setBeanFactory(PersistenceExceptionTranslationInterceptor.Java:117)
at org.springframework.data.repository.core.support.PersistenceExceptionTranslationRepositoryProxyPostProcessor.<init>(PersistenceExceptionTranslationRepositoryProxyPostProcessor.Java:44)
at org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport.setBeanFactory(TransactionalRepositoryFactoryBeanSupport.Java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.Java:1502)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1470)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:521)
... 33 more
Qu'est-ce que je manque ou fais mal?
MODIFIER
Suite à la réponse de @SotiriosDelimanolis, j'ai modifié mon code pour lire ce qui suit:
@Autowired DataSource dataSource;
@Autowired EntityManagerFactory entityManagerFactory;
@Bean
public JndiObjectFactoryBean dataSource() {
// configure and return the necessary JDBC DataSource
JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean();
dataSource.setJndiName("Java:comp/env/jdbc/josak");
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceUnitName("persistenceUnit");
emf.setDataSource(dataSource);
return emf;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory);
}
Mais je reçois des exceptions Autowired à la place maintenant:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.sql.DataSource com.ia.system.configuration.AppConfigJPA.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:514)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.Java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:285)
... 31 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.Java:988)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.Java:858)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.Java:770)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:486)
... 33 more
veuillez vous référer au lien ci-dessous -
la source de données doit être créée comme ceci -
@Bean
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
DataSource dataSource = dsLookup.getDataSource("jdbc/yourJdbcGoesHere");
return dataSource;
}
C'est une conception bizarre (pour PersistenceExceptionTranslator
) que je ne comprends pas immédiatement, mais voici la solution.
Votre LocalContainerEntityManagerFactoryBean
est un FactoryBean
mais aussi un PersistenceExceptionTranslator
(implémente les deux). Mais vous ne mettez pas le LocalContainerEntityManagerFactoryBean
dans votre contexte, vous obtenez seulement son objet créé.
Au lieu de
@Bean
public EntityManagerFactory entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceUnitName("persistenceUnit");
emf.setDataSource(dataSource());
emf.afterPropertiesSet
return emf.getObject();
}
faire
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceUnitName("persistenceUnit");
emf.setDataSource(dataSource());
return emf;
}
@Autowired
private EntityManagerFactory entityManagerFactory;
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory);
}
Spring se chargera d'appeler afterPropertiesSet()
et getObject()
pour mettre un bean EntityManagerFactory
dans le contexte.
Fondamentalement, vous vous retrouvez avec deux beans, un EntityManagerFactory
et un LocalContainerEntityManagerFactoryBean
. Votre configuration JPA nécessite un bean PersistenceExceptionTranslator
dans le contexte. Cela sera satisfait par LocalContainerEntityManagerFactoryBean
.
Pour info, vous pouvez faire la même chose pour votre JndiObjectFactoryBean
ou tout autre FactoryBean
.