Java 如何使用 Spring @Configuration 而不是 XML 配置来检索 JNDI
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19431517/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to retrieve JNDI using Spring @Configuration instead of XML configuration
提问by Eric B.
I've started development of a new Spring 3.2.4 application and am trying to use Java based configuration instead of XML files as I have used in the past. However, I am having trouble making the transition.
我已经开始开发一个新的 Spring 3.2.4 应用程序,并尝试使用基于 Java 的配置而不是我过去使用的 XML 文件。但是,我在进行转换时遇到了麻烦。
Using XML, I would code it as follows:
使用 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>
However, I am very much stuck trying to figure out how to do this in Java. I'm trying to replicate the configuration, but running into trouble:
但是,我一直在试图弄清楚如何在 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());
}
}
However, I get the following error message:
但是,我收到以下错误消息:
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
What am I missing or doing wrong?
我错过了什么或做错了什么?
EDIT
编辑
Following @SotiriosDelimanolis response, I have modified my code to read the following:
在@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);
}
But am getting Autowired exceptions instead now:
但是现在我收到了 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
回答by Sotirios Delimanolis
This is a weird design (for PersistenceExceptionTranslator
) that I don't immediately understand, but here is the solution.
这是一个奇怪的设计(for PersistenceExceptionTranslator
),我不能立即理解,但这是解决方案。
Your LocalContainerEntityManagerFactoryBean
is a FactoryBean
but also a PersistenceExceptionTranslator
(implements both). But you aren't putting the LocalContainerEntityManagerFactoryBean
into your context, you are only getting its created object.
你LocalContainerEntityManagerFactoryBean
是一个FactoryBean
但也是一个PersistenceExceptionTranslator
(同时实现)。但是您并没有将LocalContainerEntityManagerFactoryBean
放入您的上下文中,您只是获得了它创建的对象。
Instead of
代替
@Bean
public EntityManagerFactory entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceUnitName("persistenceUnit");
emf.setDataSource(dataSource());
emf.afterPropertiesSet
return emf.getObject();
}
do
做
@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 will take care of calling afterPropertiesSet()
and getObject()
to put a EntityManagerFactory
bean into the context.
Spring将采取调用的照顾afterPropertiesSet()
,并getObject()
把一个EntityManagerFactory
Bean注入的上下文。
Basically you end up with two beans, a EntityManagerFactory
and a LocalContainerEntityManagerFactoryBean
. Your JPA configuration requires a PersistenceExceptionTranslator
bean in the context. That will be satisfied by LocalContainerEntityManagerFactoryBean
.
基本上你最终会得到两个 bean, aEntityManagerFactory
和 a LocalContainerEntityManagerFactoryBean
。您的 JPA 配置需要PersistenceExceptionTranslator
上下文中的bean。这将满足LocalContainerEntityManagerFactoryBean
。
FYI, you can do the same thing for your JndiObjectFactoryBean
or any other FactoryBean
.
仅供参考,您可以为您的JndiObjectFactoryBean
或任何其他FactoryBean
.
回答by Raj
please refer below link -
请参考以下链接 -
the datasource need to be created like this -
需要像这样创建数据源 -
@Bean
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
DataSource dataSource = dsLookup.getDataSource("jdbc/yourJdbcGoesHere");
return dataSource;
}