【发布时间】:2018-06-22 01:12:23
【问题描述】:
我是 Spring 框架的新手,我正在尝试从我的朋友的简单应用程序开始,它将收集关于我们公司的八卦。
我无法将持久化存储库注入服务层的问题。
这是进入域的唯一类(Gossip.java):
package ru.gossips.core.domain;
public class Gossip {
private Long id;
private String text;
public Gossip() {
}
public Gossip(Long id, String text) {
this.id = id;
this.text = text;
}
... getters and setters omitted
}
这是他在持久层中的兄弟类(PGossip.java):
package ru.gossips.persistence.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class PGossip {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String text;
protected PGossip() {
}
public PGossip(String author, String text) {
this.text = text;
}
... getters and setters omitted
@Override
public String toString() {
return String.format(
"Persistence: Gossip[id=%d, text='%s']",
id, text);
}
}
我还有一个八卦存储库:
package ru.gossips.persistence.repository;
import org.springframework.data.repository.CrudRepository;
import ru.gossips.persistence.domain.PGossip;
public interface GossipRepository extends CrudRepository<PGossip, Long> {
}
... 和八卦服务:
package ru.gossips.core.services;
import ru.gossips.core.domain.Gossip;
import java.util.List;
public interface GossipService {
List<Gossip> requestAllGossips();
}
它的实现:
package ru.gossips.core.services;
import org.springframework.beans.factory.annotation.Autowired;
import ru.gossips.core.domain.Gossip;
import ru.gossips.persistence.repository.GossipRepository;
import ru.gossips.persistence.domain.PGossip;
import java.util.ArrayList;
import java.util.List;
public class GossipServiceImpl implements GossipService {
// PROBLEM HERE!!!!
@Autowired
private GossipRepository gossipRepository;
@Override
public List<Gossip> requestAllGossips() {
// converting all persistence gossips to domain gossips
final List<Gossip> gossipList = new ArrayList<Gossip>();
for (PGossip pGossip : gossipRepository.findAll()) {
gossipList.add(new Gossip(pGossip.getId(), pGossip.getText()));
}
return gossipList;
}
}
在这里我收到了来自 IntelliJ IDEA 的警告:必须在有效的 spring bean 中定义自动装配的成员。
不过,我已经按照Spring Data Jpda Reference v 1.4.3做了所有需要做的事情:
- 声明一个扩展 Repository 或其子接口之一的接口并将其键入到它将处理的域类 - 完成
- 在接口上声明查询方法 - 我只使用 CrudRepository 提供的方法
- 设置 Spring 为这些接口创建代理实例 - 最困难的一步。由于我使用 Java 配置 而不是 xml 配置,因此我创建了 Persitence 配置(见下文)
- 获取存储库实例并使用它 - 我收到警告。
我的持久性配置:
package ru.gossips.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType.H2;
@Configuration
@EnableJpaRepositories(basePackages = "ru.gossips.persistence.repository")
@EnableTransactionManagement
public class PersistenceConfig {
@Bean
public DataSource dataSource() {
//todo: how to make non-embedded database?
return new EmbeddedDatabaseBuilder().setType(H2).build();
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.H2);
return hibernateJpaVendorAdapter;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
@Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(jpaVendorAdapter());
factory.setDataSource(dataSource());
factory.setPackagesToScan("ru.gossips.persistence.domain");
factory.afterPropertiesSet();
return factory.getObject();
}
}
我还有WebApplicationInitializer 和PersistenceConfig 中提到的getRootConfigClasses(),还有CoreConfig 和DomainConfig。
然而,在花了大约一周的时间试图了解出了什么问题后,我无法摆脱一种强烈的感觉,即我错过了我的配置/代码中的一些非常愚蠢的错误。
可能出了什么问题?
提前致谢!
已添加:CoreConfig.java:
package ru.gossips.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.gossips.core.services.GossipService;
import ru.gossips.core.services.GossipServiceImpl;
@Configuration
public class CoreConfig {
@Bean
public GossipService gossipService() {
return new GossipServiceImpl();
}
}
添加: 这是我在部署应用程序时得到的实际堆栈跟踪:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.gossips.persistence.repository.GossipRepository ru.gossips.core.services.GossipServiceImpl.gossipRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipRepository': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:381)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1558)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:620)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:567)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1487)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:97)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1328)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1420)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:848)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.gossips.persistence.repository.GossipRepository ru.gossips.core.services.GossipServiceImpl.gossipRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipRepository': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 56 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipRepository': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:957)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 58 more
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:118)
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:1572)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1540)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
... 67 more
解决方案:
非常感谢@RC 的解决方案。
简短的解决方案:将此 bean 添加到您的配置中:
@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator(){
return new HibernateExceptionTranslator();
}
解决方案说明:link
【问题讨论】:
-
你如何向 Spring 介绍
GossipServiceImpl类?你通常会在GossipServiceImpl上有一个@Component或@Service(现在,完全等效)注释。我没有看到您明确告诉 Spring 创建一个GossipServiceImplbean 的任何地方,而 IntelliJ 可能会弄清楚这一点并警告您。 -
@chrylis 我在 CoreConfig 中注册了这个 bean(刚刚将代码添加到消息中)。之后我将
GossipServiceImpl注入网络层。但是,我的问题是GossipRepository,而不是GossipServiceImpl。 -
没关系 IntelliJ.. 实际的堆栈跟踪显示是什么?
-
@Kite,有点友好的建议,下次尝试用谷歌搜索异常。 :)
标签: java spring spring-data-jpa