简体   繁体   English

将Spring持久性存储库注入服务层

[英]Inject spring persistence repository into service layer

I'm new to spring framework and I'm trying to start from the simple application for my friends which will collect gossips about our company. 我是spring框架的新手,我正尝试从为我的朋友准备的简单应用程序开始,该应用程序将收集有关我们公司的八卦。

The problem that I'm unable to inject persistence repository into service layer. 我无法将持久性存储库注入服务层的问题。

Here is the only class into domain (Gossip.java): 这是进入域(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
}

Here is his sibling class in the persistence layer (PGossip.java): 这是他在持久层(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);
    }
}

I also have a repository for gossips: 我也有一个八卦的存储库:

package ru.gossips.persistence.repository;

import org.springframework.data.repository.CrudRepository;
import ru.gossips.persistence.domain.PGossip;

public interface GossipRepository extends CrudRepository<PGossip, Long> {
}

... and a gossip service: ...以及八卦服务:

package ru.gossips.core.services;

import ru.gossips.core.domain.Gossip;

import java.util.List;

public interface GossipService {
    List<Gossip> requestAllGossips();
}

and it's implementation: 它的实现:

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;
    }
}

And here I recieve the warning from IntelliJ IDEA: Autowired members must be defined in the valid spring bean. 在这里,我收到了IntelliJ IDEA的警告: 必须在有效的spring bean中定义自动装配的成员。

However, I've done all that need to be done according to Spring Data Jpda Reference v 1.4.3 : 但是,根据Spring Data Jpda Reference v 1.4.3 ,我已经完成了所有需要完成的工作:

  1. Declare an interface extending Repository or one of its subinterfaces and type it to the domain class that it will handle - done 声明扩展存储库的接口或其子接口之一,并将其​​键入要处理的域类- 完成
  2. Declare query methods on the interface - I use only the metods provided by CrudRepository 在接口上声明查询方法- 我仅使用CrudRepository提供的方法
  3. Set up Spring to create proxy instances for those interfaces - the most difficult step. 设置Spring为这些接口创建代理实例-这是最困难的步骤。 Since I use Java Configuration instead of xml configuration , I've created Persitence config (see below) 由于我使用Java配置而不是xml配置 ,因此我创建了Persitence配置(请参见下文)
  4. Get the repository instance injected and use it - here I get the warning. 获取注入的存储库实例并使用它-在这里我得到警告。

My persistence config: 我的持久性配置:

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();
    }
}

I also have WebApplicationInitializer with PersistenceConfig mentioned in getRootConfigClasses() , also have CoreConfig and DomainConfig . 我也有在getRootConfigClasses()提到的带有PersistenceConfig WebApplicationInitializer ,也有CoreConfigDomainConfig However, after spending about a week trying to understand what's going wrong I can't get out of the strong feeling that I've missed some really stupid mistake in my configuration/code. 但是,在花了大约一周的时间试图了解问题所在之后,我无法摆脱强烈的感觉,我错过了配置/代码中一些非常愚蠢的错误。

What could be wrong? 有什么事吗

Thanks in advance! 提前致谢!

Added : CoreConfig.java : 添加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();
    }
}

Added: Here is the actual stack trace I get while deploying app: 补充:这是我在部署应用程序时获得的实际堆栈跟踪:

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

THE SOLUTION: 解决方案:

Big thanks @RC for the solution. 非常感谢@RC提供的解决方案。

Short solution: add this bean to your config: 简短的解决方案:将此bean添加到您的配置中:

@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator(){
    return new HibernateExceptionTranslator();
}

And solution explained: link 并解释解决方案: 链接

Add @Repository over interface GossipRepository as it will mark it as a repository bean in the spring framework and will be taken care by spring container. 通过GossipRepository接口添加@Repository,因为它将在Spring框架中将其标记为存储库bean,并且将由spring容器处理。

Also add @Component over the service class and interface eg in your problem GossipService and GossipServiceImpl to register the classes with spring container 还要在服务类和接口上添加@Component,例如在您的问题GossipService和GossipServiceImpl中,以在spring容器中注册类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM