【问题标题】:Generic class Implementation for a SpringData & QueryDSL ServiceSpringData 和 QueryDSL 服务的通用类实现
【发布时间】:2015-12-14 11:31:46
【问题描述】:

我有一堆服务类,它们具有扩展 JpaRepository 和 QueryDslPredicateExecutor 的存储库。 除了它处理的实体之外,服务类中的方法是相同的。我正在尝试创建 一个通用的服务类,但我得到一个“资源依赖注入失败;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖找到类型 [pkg.BaseRepository] ​​的合格 bean:预计至少有 1 个合格的 bean作为此依赖项的自动装配候选者”。

以下是我的课程:

//BaseRepository.java
@NoRepositoryBean
public interface BaseRepository<T> extends JpaRepository<T, Long>, QueryDslPredicateExecutor<T> {}

//RegionRepository.java
@Repository
public interface RegionRepository<Region> extends JpaRepository<Region, Long>, QueryDslPredicateExecutor<Region> {}

//ProvinceRepository.java
@Repository
public interface ProvinceRepository<Province> extends JpaRepository<Province, Long>, QueryDslPredicateExecutor<Province> {}

... 以及更多 XxxRepository 接口

//AbstractBaseService.java
public abstract class AbstractBaseService<T>{
    @Autowired 
    private BaseRepository<T> repository;

    public void add(T entity) {
        System.out.println("Adding entity " + entity.getClass());
    }

    public T retrieve(Long id) {
        System.out.println("Retrieving region with dbId = " + id);
        return repository.findOne(id);
    }

    public List<T> findAll() {
        return repository.findAll();
    }
    ...
    //some other methods

}

//RegionService.java
@Service("regService")
public class RegionService extends AbstractBaseService<Region> {}

//ProvinceService.java
@Service("provService")
public class ProvinceService extends AbstractBaseService<Province> {}


@Controller
public class MyController {

    public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("/spring/application-context.xml");

        MyController controller = new MyController();
        controller.run(context);
    }

    public void run(ApplicationContext context) {       
        RegionService regService =  (RegionService)context.getBean("regService");
        Region reg = regService.retrieve(1L);
    }
}

我的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
      http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
    version="2.1">

    <persistence-unit name="generics" transaction-type="RESOURCE_LOCAL">      
        <properties>
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
        </properties>
    </persistence-unit>
</persistence>

application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/data/jpa 
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- Root Context: defines shared resources visible to all other web components -->
    <context:component-scan base-package="com.dreamcorps.gen" />

    <bean id="placeholderConfig"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:spring/db.properties" />
    </bean>

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database"           value="${jpa.dbVendor}" />
                <property name="databasePlatform"   value="${jpa.dialect}"  />
                <property name="showSql"            value="${jpa.showSql}"  />  
                <property name="generateDdl"        value="false" />
            </bean>
        </property> 
        <property name="persistenceUnitName" value="generics" />    
    </bean>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <!-- access -->
        <property name="driverClass"                value="${jdbc.driver}"/>
        <property name="jdbcUrl"                    value="${jdbc.url}"/>
        <property name="user"                       value="${jdbc.username}"/>
        <property name="password"                   value="${jdbc.password}"/>

        <!-- pool sizing -->
        <property name="initialPoolSize"            value="${c3p0.initialPoolSize}"/>
        <property name="minPoolSize"                value="${c3p0.minPoolSize}"/>
        <property name="maxPoolSize"                value="${c3p0.maxPoolSize}"/>
        <property name="acquireIncrement"           value="${c3p0.acquireIncrement}"/>
        <property name="maxStatements"              value="${c3p0.maxStatements}"/>

    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    </bean>

    <tx:annotation-driven />
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <jpa:repositories base-package="com.dreamcorps.gen" />

</beans>

下面是 MyController 运行时的错误日志。

Dec 12, 2015 12:49:35 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.3.Final}
Dec 12, 2015 12:49:35 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Dec 12, 2015 12:49:35 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Dec 12, 2015 12:49:36 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
Dec 12, 2015 12:49:36 AM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator initiateService
WARN: HHH000181: No appropriate connection provider encountered, assuming application will be supplying connections
Dec 12, 2015 12:49:36 AM org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator initiateService
WARN: HHH000342: Could not obtain connection to query metadata : The application must supply JDBC connections
Dec 12, 2015 12:49:36 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Dec 12, 2015 12:49:36 AM org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl makeLobCreatorBuilder
INFO: HHH000422: Disabling contextual LOB creation as connection was null
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'regionServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:311)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.dreamcorps.sample.controller.MyController.main(MyController.java:18)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:508)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:486)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:615)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:308)
    ... 13 more
Caused by: java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
    at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:210)
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:68)
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:67)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:142)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:89)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:71)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:185)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
    ... 28 more


Is there a way to make the AbstractBaseService work as I envision above so that I don't have to create the one Service class with the same implementation as AbstractBaseService for each of my entities (Region, Province, User, Vehicle.... etc)?

任何帮助将不胜感激。

提前致谢, 马里奥

【问题讨论】:

    标签: java spring generics querydsl


    【解决方案1】:
    //RegionRepository.java
    @Repository
    public interface RegionRepository<Region> extends JpaRepository<Region, Long>, QueryDslPredicateExecutor<Region> {}
                                      ^^^^^^ Here you are actually making a new Type Variable, which is bounded to Object.
    

    您正在创建新的类型变量,这实际上隐藏了您正在为其创建存储库的类名称。

    【讨论】:

    • 鲁本,感谢您的快速回复/评论。我此时实际上正在与仿制药作斗争。你能指导或给我额外的建议,告诉我应该用 BaseRepository 或 Region/Province 存储库做什么。
    • 只有BaseRepository&lt;T&gt;应该有类型参数,RegionRepository implements BaseRepository&lt;Region&gt;应该只填写接口的空白,不能声明额外的类型参数。
    【解决方案2】:

    我终于能够让我原来的帖子工作了。缺少的是 BaseRepository.java 接口上的 @NoRepositoryBean 注释和 RegionRepository/ProvinceRepository 接口上的 @Repository 注释,如上所述。

    【讨论】:

    • 请不要用答案编辑您的问题。现在我们不再看到最初的问题了。相反,保持问题不变并在答案中写下解决方案。
    猜你喜欢
    • 2018-10-24
    • 2017-12-22
    • 2016-09-19
    • 1970-01-01
    • 2016-09-12
    • 2020-01-21
    • 2011-09-07
    • 2018-09-19
    • 1970-01-01
    相关资源
    最近更新 更多