1

我尝试使用 jpa/jdbc 设置 h2 数据库,在使用 jpa 而不是 jdbc 创建查询接口的实现之后,我现在收到错误:

com.nsa.charitystarter.service.CharityQueries 中构造函数的参数 0 需要单个 bean,但找到了 2 个:-charityRepoJDBC:在文件 [C:\Users\V La Roche\Desktop\assessment-1-starter\out\ 中定义production\classes\com\nsa\charitystarter\data\CharityRepoJDBC.class] -charityRepoJPA:在 null 中定义

我不确定出了什么问题,也不确定从哪里开始,我无法在网上找到很多与我有类似问题的人。

我使用 jdbc 的实现

@Repository
public class CharityRepoJDBC implements CharityRepository {

    private JdbcTemplate jdbc;
    private RowMapper<Charity> charityMapper;

    @Autowired
    public CharityRepoJDBC(JdbcTemplate aTemplate) {
        jdbc = aTemplate;


        charityMapper = (rs, i) -> new Charity(
                rs.getLong("id"),
                rs.getString("name"),
                rs.getString("registration_id"),
                rs.getString("acronym"),
                rs.getString("purpose")
        );
    }

    @Override
    public List<Charity> findCharityBySearch(String searchTerm) {

        String likeSearch = "%" + searchTerm + "%";

        return jdbc.query(
                "select id, acronym, name, purpose, logo_file_name, registration_id  " +
                        "from charity " +
                        "where concat(name, acronym, purpose, registration_id) like ?",
                new Object[]{likeSearch},
                charityMapper);
    }

    @Override
    public Optional<Charity> findById(Long id) {
        return Optional.of(
                jdbc.queryForObject(
                        "select id, acronym, name, purpose, logo_file_name, registration_id  from charity where id=?",
                        new Object[]{id},
                        charityMapper)
        );
    }
}

慈善查找器实施:

@Service
public class CharityQueries implements CharityFinder {
    private CharityRepository charityRepository;


    public CharityQueries(CharityRepository repo) {
        charityRepository = repo;
    }

    public Optional<Charity> findCharityByIndex(Integer index) {
        return charityRepository.findById(index.longValue());
    }

    public List<Charity> findCharityBySearch(String searchTerm) {

        return charityRepository.findCharityBySearch(searchTerm);
    }
}

CharityFinder 界面

public interface CharityFinder {

    public Optional<Charity> findCharityByIndex(Integer index);

    public List<Charity> findCharityBySearch(String searchTerm);

}

错误日志:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.nsa.charitystarter.service.CharityQueries required a single bean, but 2 were found:
    - charityRepoJDBC: defined in file [C:\Users\V La Roche\Desktop\assessment-1-starter\out\production\classes\com\nsa\charitystarter\data\CharityRepoJDBC.class]
    - charityRepoJPA: defined in null


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed


Process finished with exit code 0
4

3 回答 3

1

您似乎在类路径上有 Spring Data JDBC starter 和 Spring Data JPA starter。

Spring Data JDBC 有一个错误导致它为存储库接口生成实现,即使它不应该,因此您最终会得到一个来自 JPA 的实现和另一个来自 JDBC 的实现。

如果你真的想使用 Spring Data JDBC 和 Spring Data JPA,你可以使用 include 和 exclude 过滤器来限制@EnableJdbcRepositories和注解。@EnableJpaRepositories

但是从您的代码和您使用的标签中,我怀疑您可能对 Spring Data Jdbc 完全不感兴趣,而只对 Spring Jdbc 感兴趣。如果是这种情况,请查找依赖项spring-boot-starter-data-jdbc并将其更改为spring-boot-starter-jdbc.

万一所有这些 Spring (Data) JDBC/JPA 让您对这个问题感到困惑,它的答案可能会有所帮助:Spring Data JDBC / Spring Data JPA vs Hibernate

于 2019-11-03T18:20:12.977 回答
1

您目前有以下定义,

@Repository
public class CharityRepoJDBC implements CharityRepository {

你正在注入CharityRepository你的服务层CharityQueries

@Service
public class CharityQueries implements CharityFinder {
    private CharityRepository charityRepository;

因此,当您部署应用程序时,容器就是confused您尝试自动装配到服务中的 bean。

默认情况下,弹簧按类型自动装配,因此有 2 个 bean 有资格被弹簧容器注入。

  1. CharityRepository本身和其他
  2. CharityRepoJDBC

因此,在这种情况下,您需要明确告诉容器您要尝试自动装配哪个 bean。

因此,您可以尝试添加如下限定符来解决问题。

@Service
    public class CharityQueries implements CharityFinder {
        @Qualifier("CharityRepoJDBC")
        private CharityRepository charityRepository;

同时将您的 CharityRepoJDBC 修改为,

@Repository(value = "CharityRepoJDBC")
public class CharityRepoJDBC implements CharityRepository {
于 2019-11-03T09:55:10.643 回答
0

我解决了将 @Primary 注释放在存储库界面中的问题。在您的情况下,它将是以下内容:

@Primary
public interface CharityFinder {

    public Optional<Charity> findCharityByIndex(Integer index);

    public List<Charity> findCharityBySearch(String searchTerm);

}
于 2020-06-19T00:04:24.150 回答