Java 使用泛型实体的Spring JpaRepository

Java 使用泛型实体的Spring JpaRepository,java,spring,hibernate,generics,spring-data-jpa,Java,Spring,Hibernate,Generics,Spring Data Jpa,我正试图实现这样一个通用DAO,以便将其与X个非常相似的实体(id、代码、描述)一起使用: 我有一个需要使用Dao的服务: @Service public class TestServiceImpl implements TestService { private GenericDao<Test> testDao; @Autowired public TestServiceImpl(GenericDao<Test> testDao) {

我正试图实现这样一个通用DAO,以便将其与X个非常相似的实体(id、代码、描述)一起使用:

我有一个需要使用Dao的服务:

@Service
public class TestServiceImpl implements TestService {

    private GenericDao<Test> testDao;

    @Autowired
    public TestServiceImpl(GenericDao<Test> testDao) {
        this.testDao = testDao;
    }
}
@服务
公共类TestServiceImpl实现TestService{
私有GenericDao testDao;
@自动连线
公共TestServiceImpl(GenericDao testDao){
this.testDao=testDao;
}
}
当我使用SpringBoot启动应用程序时,应用程序不会启动,错误为:

Caused by: org.springframework.beans.factory.BeanCreationException: Error     creating bean with name 'genericDao': 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:1574)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1127)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 23 more
Caused by: java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:219)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:68)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:67)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:145)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:89)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:69)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:172)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
... 34 more
原因:org.springframework.beans.factory.BeanCreationException:创建名为“genericDao”的bean时出错:调用init方法失败;嵌套异常为java.lang.IllegalArgumentException:不是托管类型:类java.lang.Object
位于org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
位于org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
位于org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
位于org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
位于org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
位于org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
位于org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
位于org.springframework.beans.factory.support.DefaultListableBeanFactory.FindAuthories(DefaultListableBeanFactory.java:1127)
位于org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
位于org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
位于org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
位于org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 23多
原因:java.lang.IllegalArgumentException:不是托管类型:类java.lang.Object
位于org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:219)
位于org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation。(JpaMetamodelEntityInformation.java:68)
位于org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:67)
位于org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:145)
位于org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetPository(JpaRepositoryFactory.java:89)
位于org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetPository(JpaRepositoryFactory.java:69)
位于org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:172)
位于org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
位于org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertieSet(RepositoryFactoryBeanSupport.java:225)
位于org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.AfterPropertieSet(JpaRepositoryFactoryBean.java:92)
位于org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
位于org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
... 34多
您不能这样做。 Spring试图在开始时创建存储库,而不是在自动连线时。但是Spring完全不知道应该使用什么样的泛型参数。因此,它试图用
对象
实例化这个存储库。但是
对象
不是实体,所以会得到相应的错误


结论:您的存储库必须是特定类型的,但不是泛型的。

通过一些调整,您可以完成您想要完成的任务

不要用@Repository标记GenericDao并使用它,而是使用注释。正如JavaDocs所述,springjpa将尝试初始化附加到JpaRepository的任何内容,但是@NoRepositoryBean允许您创建中间扩展,而您的真实存储库可以从这些中间扩展中进行扩展。您只需确保实现GenericDao类的任何东西都为T提供了一个参数

这意味着您还必须实现实际具有@Repository注释的GenericDao扩展,并在服务中使用这些dao代替generic。因此,您的代码将如下所示:

@Getter
@Setter
@Entity
@Table(name = "TEST")
public class Test {...}
通用Dao:

@NoRepositoryBean
public interface GenericDao<T> extends JpaRepository<T, Long> {

    T findByCode(String code);
    T findById(Long id);
}

它叫类型擦除你是对的!我尝试进行此更新:
@Repository公共接口GenericDao扩展了JpaRepository{T findByCode(字符串代码);T findById(长id);}
。我创建了一个
@Entity公共抽象类BaseEntity{…}
,我的所有实体都扩展了该类。应用程序启动了,但Hibernate有一个问题,因为从逻辑上讲,它不是一个真正的表DB@nicola尝试用MappedSuperclass注释标记抽象基类。
@NoRepositoryBean
public interface GenericDao<T> extends JpaRepository<T, Long> {

    T findByCode(String code);
    T findById(Long id);
}
@Repository
public interface TestDao extends GenericDao<Test> {

}
@Service
public class TestServiceImpl implements TestService {

    private TestDao testDao;

    @Autowired
    public TestServiceImpl(TestDao testDao) {
        this.testDao = testDao;
    }
}