spring-data-jpa SimpleJpaRepository参数编译错误

oaxa6hgo  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(140)

我尝试扩展SimpleJpaRepository,但出现错误:

[ERROR]     constructor org.springframework.data.jpa.repository.support.SimpleJpaRepository.SimpleJpaRepository(org.springframework.data.jpa.repository.support.JpaEntityInformation<com.bnpparibas.dsibddf.ap00437.successione2e.domain.entity.gedeo.Contrat,?>,javax.persistence.EntityManager) is not applicable
[ERROR]       (actual and formal argument lists differ in length)
[ERROR]     constructor org.springframework.data.jpa.repository.support.SimpleJpaRepository.SimpleJpaRepository(java.lang.Class<com.bnpparibas.dsibddf.ap00437.successione2e.domain.entity.gedeo.Contrat>,javax.persistence.EntityManager) is not applicable
[ERROR]       (actual and formal argument lists differ in length)

我尝试了如下所述的@enableJpaRepositories解决方案:Extend SimpleJpaRepository但是它不起作用。我把注解放在repository类中。
我还能做些什么吗?

@Configuration
@EnableJpaRepositories(repositoryBaseClass = ContratRepository.class , basePackages = {"com.bnpparibas.dsibddf.ap00437.successione2e.infrastructure.repository"})
@Repository
public class ContratRepository extends SimpleJpaRepository<Contrat,Integer> implements IContratRepository {

    @Override
    public Contrat save(Contrat contrat) {
        return null;
    }
}

如果我按照eclipse的建议使用构造函数2:

public ContratRepository(Class<Contrat> domainClass, EntityManager em) {
        super(domainClass, em);
    }

合同类别

package com.bnpparibas.dsibddf.ap00437.successione2e.domain.entity.gedeo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Contrat {
  @Id
  @GeneratedValue(strategy = GenerationType. IDENTITY )
  private String idContratTech;

  private String contractExternalId;

  private String code;

  private String libelle;

  private String contractStatus;

  public String getIdContratTech() {
    return idContratTech;
}

public void setIdContratTech(String idContratTech) {
    this.idContratTech = idContratTech;
}

public String getContractExternalId() {
    return contractExternalId;
}

public void setContractExternalId(String contractExternalId) {
    this.contractExternalId = contractExternalId;
}

public String getCode() {
    return code;
}

public void setCode(String code) {
    this.code = code;
}

public String getLibelle() {
    return libelle;
}

public void setLibelle(String libelle) {
    this.libelle = libelle;
}

public String getContractStatus() {
    return contractStatus;
}

public void setContractStatus(String contractStatus) {
    this.contractStatus = contractStatus;
}

public String getNature() {
    return nature;
}

public void setNature(String nature) {
    this.nature = nature;
}

private String nature;

  public void foo() {
  }

}

我已经得到了错误:

NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Class<com.bnpparibas.dsibddf.ap00437.successione2e.domain.entity.gedeo.Contrat>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

我不明白
谢谢你的帮助

bvpmtnay

bvpmtnay1#

首先,你不应该把@Repository@Configuration放在同一个类上。其次,如果你要扩展SimpleJpaRepository,你需要创建匹配的构造函数并调用父构造函数。第三,我想指出的是,定制SimpleJpaRepository不建议用于单个实体(例如Contrat)。在这种情况下,请使用常规的存储库实现!如果您确实将SimpleJpaRepository定制为仅与单个实体兼容,则您将无法创建其他扩展SimpleJpaRepository的存储库

1.关于Bean和配置

Spring,a Repositorybean的一种类型。这意味着,当您需要该类的示例时,Spring框架可以自动示例化该类(是否注意到您从来不需要执行new MyRepository()?)。这是通过一个称为 autowiring 的过程来完成的(其一般原理称为Dependency Injection。你可以在spring here中阅读更多关于bean和自动装配的内容。其他典型的bean类型有@Component@Controller@Service
另一方面,Configuration类是一种完全不同的类。Configuration classes用于提供关于如何创建某些bean的逻辑
例如,您要配置一个保存数据库连接的Bean,并且为了创建该Bean,您需要从环境中读取变量(环境变量)。在该示例中,配置类将是阅读环境变量并通过@Bean方法创建数据库连接Bean的类。
因此,本质上,配置类用于示例化1)不能自动示例化或2)需要特殊bean配置的bean。

2.关于匹配构造函数

Spring需要能够示例化父类SimpleJpaRepository。因此,您应该确保实现匹配的构造函数。此外,将存储库拆分为RepositoryRepositoryImpl是一个通用的最佳实践。
因此,对于构造函数匹配,它给出:

自定义简单存储库实现

public class CustomSimpleRepositoryImpl(<T, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> extends CustomSimpleRepository<T, ID> {

    private EntityManager em;
    private JpaEntityInformation<T, ?> ei;

    protected CustomSimpleRepositoryImpl(@NonNull Class<T> entityClass, EntityManager em) {
        super(domainClass, em);
        this.em = em;
        this.ei= JpaEntityInformationSupport.getEntityInformation(entityClass, em);
    }

    public CustomSimpleRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.em = entityManager;
        this.ei = entityInformation;
    }

    /* Whatever you want to put in your repository */
}

对于拆分:自定义简单存储库

@NoRepositoryBean
public interface CustomJpaRepository<T, ID extends Serializable> extends JpaRepository<T, ID>  {
    /* Whatever you want to put in your repository */
}

3.自定义存储库

请注意,在上面的例子中,我没有使用@Repository,而是使用了@NoRepositoryBean。这是因为在我的例子中,我实现了一个 * 通用的SimpleJpaRepository替换 *。这个仓库不能自己示例化!

3.1普通的自定义存储库

如果您希望自定义常规Repository,请仅使用接口CustomRepository和名为CustomRepositoryImpl的实现。
示例实现可在3.2中找到。

3.2扩展SimpleJpaRepository的自定义存储库

这是一个困难的问题:如果不提供接口所有未实现的方法,你就无法实现接口。2所以如果你真的想要一个同时拥有以下两种方法的仓库:

  1. JPA方法,例如findByIdfindByFieldContainsText(String text)...
    1.自定义方法,例如findAllCountsGroupByParentId()...
    创建一个单独的仓库接口或类是不可能的,相反,您需要创建一个自定义仓库,在其中卸载您的“自定义方法”(2),并创建一个扩展SimpleJpaRepository的仓库,在其中定义您的“JPA方法”(1):

自定义JpaRepository.java

@Repository
public interface CustomJpaRepository
        extends JpaRepository<CustomEntity, Long>
        extends CustomRepository {
    /* Your desired JPA methods, e.g. */
    // findByNameContainsText(String text);
}

自定义存储库.java

public interface CustomRepository {
    /* Your desired custom methods, e.g. */
    // findAllCountsWhereContractFinishedGroupByBusinessUnitId();
}

自定义资料档案库实现java

@Repository
public class CustomRepositoryImpl {

    protected EntityManager em;

    CustomRepositoryImpl(final EntityManager em) {
        this.em = em;
    }

    /* Your desired custom methods, e.g. */
    // public findAllCountsWhereContractFinishedGroupByBusinessUnitId() {
    //    ...
    // }
}

因为CustomJpaRepository扩展了JpaRepository,所以可以使用JPA方法。因为它也扩展了CustomRepository,所以它继承了自定义方法。结果:您可以调用在CustomJpaRepository中组合的两种方法(custom和jpa)。

相关问题