私は新しいSpring 3.2.4アプリケーションの開発を開始し、以前使用していたXMLファイルの代わりにJavaベースの構成を使用しようとしています。しかし、遷移。
XMLを使用して、次のようにコーディングします。
<!-- 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>
ただし、Javaでこれを行う方法を理解しようとするのは非常に困難です。設定を複製しようとしていますが、問題が発生しています:
@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());
}
}
ただし、次のエラーメッセージが表示されます。
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
何が欠けているか、間違っていますか?
[〜#〜] edit [〜#〜]
@SotiriosDelimanolis応答に続いて、次のコードを読み取るようにコードを変更しました。
@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);
}
しかし、代わりにAutowiredの例外が発生しています。
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
以下のリンクを参照してください-
データソースはこのように作成する必要があります-
@Bean
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
DataSource dataSource = dsLookup.getDataSource("jdbc/yourJdbcGoesHere");
return dataSource;
}
これは奇妙なデザイン(PersistenceExceptionTranslator
用)ですが、すぐには理解できませんが、解決策があります。
あなたのLocalContainerEntityManagerFactoryBean
はFactoryBean
ですが、PersistenceExceptionTranslator
でもあります(両方実装)。ただし、LocalContainerEntityManagerFactoryBean
をコンテキストに入れず、作成されたオブジェクトのみを取得します。
の代わりに
_@Bean
public EntityManagerFactory entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceUnitName("persistenceUnit");
emf.setDataSource(dataSource());
emf.afterPropertiesSet
return emf.getObject();
}
_
行う
_@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はafterPropertiesSet()
およびgetObject()
を呼び出してEntityManagerFactory
Beanをコンテキストに配置します。
基本的には、2つのBean、EntityManagerFactory
とLocalContainerEntityManagerFactoryBean
になります。 JPA構成では、コンテキストにPersistenceExceptionTranslator
Beanが必要です。それはLocalContainerEntityManagerFactoryBean
によって満たされます。
参考までに、あなたのJndiObjectFactoryBean
や他のFactoryBean
についても同じことができます。