Spring Boot 将 CrudRepository 注入服务 [英] Spring Boot Inject CrudRepository into Service

查看:41
本文介绍了Spring Boot 将 CrudRepository 注入服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难将 CrudRepository 注入使用 @Service 注释的服务中.我有两个包,一个是包含 @Service 定义和可重用控制器定义的核心"包.

I am having difficulty injecting a CrudRepository into a service annotated with the @Service annotation. I have two packages one "core" package containing @Service definitions and reusable controller definitions.

我在x.y.application包中的主要应用如下:

My main application in the x.y.application package is as follows:

package x.y.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan({ "x.y.application", "x.y.core" })
public class Application  {

    public static void main( String[] args ) {
        SpringApplication.run( Application.class, args );
    }

}

然后是一个示例控制器.

Then an example Controller.

package x.y.application.controller;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

import x.y.application.model.User;
import x.y.core.controller.Controller;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import org.springframework.data.repository.CrudRepository;

@RestController
@RequestMapping("/test")
public class HelloController extends Controller<User> {
}

然后是我的可重用控制器类

Then my re-usable controller class

package x.y.core.controller;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.http.HttpStatus;
import org.springframework.data.repository.CrudRepository;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.beans.factory.annotation.Autowired;

import x.y.core.service.Service;

public class Controller<T> {

    @Inject
    Service<T> service;

    @RequestMapping(value = "/index.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public T create( @RequestBody T item ) throws Exception {
        return service.create( item );
    }

    @RequestMapping(value = "/{id}.json", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    public T update( @PathVariable Long id, @RequestBody T item ) throws Exception {
        return service.update( item );
    }

    @RequestMapping(value = "/{id}.json", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public T read( @PathVariable Long id ) throws Exception {
        return service.findOne( id );
    }

    @RequestMapping(value = "/index.json", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public List<T> readAll() throws Exception {
        return service.findAll();
    }

    @RequestMapping(value = "/{id}.json", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    public void delete( @PathVariable Long id ) throws Exception {
        service.delete( id );
    }

}

然后是我的服务接口

package x.y.core.service;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.lang.reflect.*;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.http.HttpStatus;
import org.springframework.data.repository.CrudRepository;
import org.springframework.dao.DataIntegrityViolationException;

public interface Service<T> {

    /**
     * create.
     * Creates a new entity in the database.
    */
    public T create( T item );

    /**
     * update.
     * Updates an existing entity in the database.
    */
    public T update( T item );

    public T findOne( Long id );

    public List<T> findAll();

    public void delete( Long id );
}

最后是有问题的服务实现.

And finally the problematic implementation of service.

package x.y.core.service;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.lang.reflect.*;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.http.HttpStatus;
import org.springframework.data.repository.CrudRepository;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.beans.factory.annotation.Autowired;

@org.springframework.stereotype.Service
public class RepositoryService<T> implements Service<T> {

    @Inject //Throws exception
    CrudRepository<T,Long> repository;

    /**
     * create.
     * Creates a new entity in the database.
    */
    public T create( T item ) throws DataIntegrityViolationException {

        /*try {
            Field field = item.getClass().getDeclaredField( "id" );
            field.setAccessible( true );
            if( repository.exists( field.getLong( item ) ) ) {
                throw new DataIntegrityViolationException( "Entity object already exists." );
            }
        } catch ( Exception exception ) {
            throw new DataIntegrityViolationException( "Entity class does not contain Id attribute." );
        }

        return repository.save( item );*/ return item;
    }

    /**
     * update.
     * Updates an existing entity in the database.
    */
    public T update( T item ) throws DataIntegrityViolationException {

        /*try {
            Field field = item.getClass().getDeclaredField( "id" );
            field.setAccessible( true );
            if( !repository.exists( field.getLong( item ) ) ) {
                throw new DataIntegrityViolationException( "Entity object does not exists." );
            }
        } catch ( Exception exception ) {
            throw new DataIntegrityViolationException( "Entity class does not contain Id attribute." );
        }

        return repository.save( item );*/ return item;
    }

    public T findOne( Long id ) {
        /*if( !repository.exists( id ) ) {
            throw new DataIntegrityViolationException( "Item with id does not exists." );
        }
        return repository.findOne( id );*/ return null;
    }

    public List<T> findAll() {
       final List<T> resultList = new ArrayList<>();
       /*/ final Iterator<T> all    = repository.findAll().iterator();

        while( all.hasNext() ) {
            resultList.add( all.next() );
        }*/

        return resultList;
    }

    public void delete( Long id ) {
        /*if( !repository.exists( id ) ) {
            throw new DataIntegrityViolationException( "Item with id does not exists." );
        }
        repository.delete( id );*/
    }
}

异常

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.repository.CrudRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}

好像任何spring注册的Component、Service、Resource都不能注入CrudRepository?但是,如果我不在 x.y.application 包中注释 CrudRepository,它会编译并注入 CrudRepository?

It seems that any spring registered Component, Service, Resource cannot inject CrudRepository? However if i do not annotate the CrudRepository in the x.y.application package it compiles and the CrudRepository is injected?

推荐答案

要使依赖注入起作用,应用程序上下文必须知道创建特定类实例的方法.实例创建方法已知的类被称为beans".您可以通过 XML 配置文件(旧学校)或注释(新学校)定义 bean.

For dependency injection to work application context has to know a recipe for creating an instance of a specific class. Classes whose instance creation recipes are known are referred to as "beans". You can define beans either via XML configuration file (old school) or annotations (new school).

您收到的错误消息指出应用程序上下文没有 CrudRepository bean,即它不知道如何创建实现此接口的类的实例.

The error message you are receiving states that the application context does not have CrudRepository bean, i.e. it does not know how to create an instance of a class that implements this interface.

要以新的方式创建 bean 定义,您可以使用 @Bean 或包含它的任何其他元注释(>@Service@Controller 等).

To create a bean definition in a new way you may annotate a class or a specific method which return instance of a specific class with @Bean or any other meta-annotation that includes it (@Service, @Controller, etc.).

如果您打算使用 Spring Data 项目套件来自动生成存储库实现,您需要使用 @Repository 这样的注释

If you intend to use Spring Data suite of projects to automate repository implementation generation, you need to annotate an interface which extends one of the core Spring Data interfaces (Repository, CrudRepository, PagingAndSortingRepository) with @Repository annotation like so

@Repository
public interface MyRepository extends CrudRepository<Entity, Long> {
}

这为应用程序上下文提供了一个 bean 定义,并让它知道您希望为您生成存储库实现.

This provides a bean definition for the application context and makes it aware that you want the repository implementation to be generated for you.

然后您可以将 MyRepository 注入服务类.

Then you can inject MyRepository to the service class.

我唯一的疑问是关于在存储库类型定义中使用的泛型类型.我希望存储库实现(您希望为您生成的实现)是特定于实体的而不是抽象的.

The only doubt I have is about the generic type to be used in repository type definition. I would expect the repository implementation (the one you want to be generated for you) to be entity-specific rather than abstract.

这篇关于Spring Boot 将 CrudRepository 注入服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆