UnsatisfiedDependencyException 和 Circular Dependency

huangapple go评论49阅读模式
英文:

UnsatisfiedDependencyException and Circular Dependency

问题

我正在尝试构建和运行一些Spring Boot遗留代码,但遇到以下错误:

org.springframework.beans.factory.UnsatisfiedDependencyException: 在文件[......\bootstrap\DataLoader.class]中定义的bean名称为'dataLoader'的bean创建错误:通过构造函数参数0表示的不满足的依赖关系;嵌套异常是org.springframework.beans.factory.UnsatisfiedDependencyException: 创建bean名称为'organizationServiceImpl'的bean时出错:通过方法'setAssessmentService'的参数0表示的不满足的依赖关系;嵌套异常是org.springframework.beans.factory.BeanCreationException: 创建bean名称为'assessmentServiceImpl'的bean时出错:调用初始化方法失败;嵌套异常是org.springframework.dao.InvalidDataAccessResourceUsageException:无法提取结果集;SQL [n/a];嵌套异常是org.hibernate.exception.SQLGrammarException:无法提取结果集
......
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 创建bean名称为'organizationServiceImpl'的bean时出错:通过方法'setAssessmentService'的参数0表示的不满足的依赖关系;嵌套异常是org.springframework.beans.factory.BeanCreationException: 创建bean名称为'assessmentServiceImpl'的bean时出错:调用初始化方法失败;嵌套异常是org.springframework.dao.InvalidDataAccessResourceUsageException:无法提取结果集;SQL [n/a];嵌套异常是org.hibernate.exception.SQLGrammarException:无法提取结果集
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:676)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
    at ........
Caused by: org.springframework.beans.factory.BeanCreationException: 创建bean名称为'assessmentServiceImpl'的bean时出错:调用初始化方法失败;嵌套异常是org.springframework.dao.InvalidDataAccessResourceUsageException:无法提取结果集;SQL [n/a];嵌套异常是org.hibernate.exception.SQLGrammarException:无法提取结果集
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139)

DataLoader类是:

@Component
public class DataLoader implements ApplicationRunner {

    private final OrganizationService organizationService;

    private List<String> organizationNames = Arrays.asList(
        // ...一些较长的字符串文字列表...
    );

    public DataLoader(OrganizationService organizationService) {
        this.organizationService = organizationService;
    }

    @Override
    public void run(ApplicationArguments args) {
        if (CollectionUtils.isEmpty(organizationService.findAll())) {
            addOrganizations();
        }
    }

    private void addOrganizations() {
        organizationNames.forEach(name -> {
            OrganizationRequest organization = new OrganizationRequest();
            organization.setName(name);
            if (
            // ....不相关的代码....
            }
            organizationService.save(organization);
        });
    }

}

OrganizationServiceImpl类是:

@Service
public class OrganizationServiceImpl implements OrganizationService {

    private final OrganizationRepository organizationRepository;
    private final AddressService addressService;
    private final ContactService contactService;
    private final SupplierQualifierService supplierQualifierService;
    private final MonitoringScopeService monitoringScopeService;
    private final FinancialService financialsService;

    private DocumentService documentService;
    private AssessmentService assessmentService;

    @Getter
    private Map<Long, Set<QuestionType>> questionTypesForAssessmentByOrganization = new HashMap<>();

    public OrganizationServiceImpl(OrganizationRepository organizationRepository, AddressService addressService, ContactService contactService, SupplierQualifierService supplierQualifierService, MonitoringScopeService monitoringScopeService, FinancialService financialsService ) {
        this.organizationRepository = organizationRepository;
        this.addressService = addressService;
        this.contactService = contactService;
        this.supplierQualifierService = supplierQualifierService;
        this.monitoringScopeService = monitoringScopeService;
        this.financialsService = financialsService;
    }

    //解决循环依赖问题
    @Autowired
    public void setAssessmentService(AssessmentService assessmentService) {
        this.assessmentService = assessmentService;
    }

    // 防止循环依赖问题...
    @Autowired 
    public void setDocumentService(DocumentService documentService) {
        this.documentService = documentService;
    }

    @Override
    public Organization findById(Long id) {
        Optional<Organization> organization = organizationRepository.findById(id);
        return organization.orElse(new Organization());
    }

    @Override
    public List<Organization> findAll() {
        return organizationRepository.findAll();
    }

    @Override
    public Organization save(OrganizationRequest request) {
    //....不相关的长代码...
        return savedOrganization;
    }

    //....不相关的长代码,一些业务逻辑...
}

AssessmentServiceImpl类是:

@Service
public class AssessmentServiceImpl implements AssessmentService {

    private final AssessmentRepository assessmentRepository;
    private final OrganizationService organizationService;
    private final AnswerService answerService;
    private final QuestionService questionService;

    private Map<QuestionType, Integer> numberOfQuestionsByType = new HashMap<>();

    public AssessmentServiceImpl(AssessmentRepository assessmentRepository, OrganizationService organizationService, AnswerService answerService, QuestionService questionService) {
        this.assessmentRepository = assessmentRepository;
        this.organizationService = organizationService;
        this.answerService = answerService;
        this.questionService = questionService;
    }

    @PostConstruct
    public void postConstruct() {
        for (QuestionType type : QuestionType.values()) {
            numberOfQuestionsByType.put(type, questionService.findByQuestionType(type).size());
        }
    }

    //...一些业务逻辑代码....
}

依赖注入失败的链路如下:

创建bean名称为'dataLoader'的bean时出错:
创建bean名称为'organizationServiceImpl'的bean时出错:
创建bean名称为'assessmentServiceImpl'的bean时出错:
但我看不到直接的原因。
我看到原始开发者遇到了循环依赖问题,但从我搜索的结果来看,这应该是适当的解决方案:
//解决循环依赖问题
@Autowired
public void setAssessmentService(AssessmentService assessmentService) {
this.assessmentService = assessment
<details>
<summary>英文:</summary>
I am trying to make some Spring Boot legacy code build and run, but it fails with:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name &#39;dataLoader&#39; defined in file [......\bootstrap\DataLoader.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name &#39;organizationServiceImpl&#39;: Unsatisfied dependency expressed through method &#39;setAssessmentService&#39; parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;assessmentServiceImpl&#39;: Invocation of init method failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
......
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name &#39;organizationServiceImpl&#39;: Unsatisfied dependency expressed through method &#39;setAssessmentService&#39; parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;assessmentServiceImpl&#39;: Invocation of init method failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:676)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at ........
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;assessmentServiceImpl&#39;: Invocation of init method failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139)
DataLoader class is:
@Component
public class DataLoader implements ApplicationRunner {
private final OrganizationService organizationService;
private List&lt;String&gt; organizationNames = Arrays.asList(
...some long list of string literals...
);
public DataLoader(OrganizationService organizationService) {
this.organizationService = organizationService;
}
@Override
public void run(ApplicationArguments args) {
if (CollectionUtils.isEmpty(organizationService.findAll())) {
addOrganizations();
}
}
private void addOrganizations() {
organizationNames.forEach(name -&gt; {
OrganizationRequest organization = new OrganizationRequest();
organization.setName(name);
if (
....irrelevant code....
}
organizationService.save(organization);
});
}
}
and OrganizationServiceImpl class is:
@Service
public class OrganizationServiceImpl implements OrganizationService {
private final OrganizationRepository organizationRepository;
private final AddressService addressService;
private final ContactService contactService;
private final SupplierQualifierService supplierQualifierService;
private final MonitoringScopeService monitoringScopeService;
private final FinancialService financialsService;
private DocumentService documentService;
private AssessmentService assessmentService;
@Getter
private Map&lt;Long, Set&lt;QuestionType&gt;&gt; questionTypesForAssessmentByOrganization = new HashMap&lt;&gt;();
public OrganizationServiceImpl(OrganizationRepository organizationRepository, AddressService addressService, ContactService contactService, SupplierQualifierService supplierQualifierService, MonitoringScopeService monitoringScopeService, FinancialService financialsService ) {
this.organizationRepository = organizationRepository;
this.addressService = addressService;
this.contactService = contactService;
this.supplierQualifierService = supplierQualifierService;
this.monitoringScopeService = monitoringScopeService;
this.financialsService = financialsService;
}
//workaround for circular dependency
@Autowired
public void setAssessmentService(AssessmentService assessmentService) {
this.assessmentService = assessmentService;
}
// to prevent circular dependency problem ...
@Autowired 
public void setDocumentService(DocumentService documentService) {
this.documentService = documentService;
}
@Override
public Organization findById(Long id) {
Optional&lt;Organization&gt; organization = organizationRepository.findById(id);
return organization.orElse(new Organization());
}
@Override
public List&lt;Organization&gt; findAll() {
return organizationRepository.findAll();
}
@Override
public Organization save(OrganizationRequest request) {
....long not relevant code...
return savedOrganization;
}
....long not relevant code, some business logic...
}
AssessmentServiceImpl class is:
@Service
public class AssessmentServiceImpl implements AssessmentService {
private final AssessmentRepository assessmentRepository;
private final OrganizationService organizationService;
private final AnswerService answerService;
private final QuestionService questionService;
private Map&lt;QuestionType, Integer&gt; numberOfQuestionsByType = new HashMap&lt;&gt;();
public AssessmentServiceImpl(AssessmentRepository assessmentRepository, OrganizationService organizationService, AnswerService answerService, QuestionService questionService) {
this.assessmentRepository = assessmentRepository;
this.organizationService = organizationService;
this.answerService = answerService;
this.questionService = questionService;
}
@PostConstruct
public void postConstruct() {
for (QuestionType type : QuestionType.values()) {
numberOfQuestionsByType.put(type, questionService.findByQuestionType(type).size());
}
}
... some business logic code....
}
Chain of failed dependency injection is:
Error creating bean with name &#39;dataLoader&#39;:
Error creating bean with name &#39;organizationServiceImpl&#39;: 
Error creating bean with name &#39;assessmentServiceImpl&#39;: 
But I don&#39;t see direct cause for it.
I see that original developer ran into cyclic dependency issues, but from what I Googled it seems this should be appropriate solution: 
//workaround for circular dependency
@Autowired
public void setAssessmentService(AssessmentService assessmentService) {
this.assessmentService = assessmentService;
}
// to prevent circular dependency problem ...
@Autowired 
public void setDocumentService(DocumentService documentService) {
this.documentService = documentService;
}
</details>
# 答案1
**得分**: 1
错误消息说明在创建Bean时与数据源有问题:
**InvalidDataAccessResourceUsageException: could not extract ResultSet**
我怀疑在读取数据库时存在问题。没有循环依赖问题。这是一个完美的Bean创建链。Spring检测到循环依赖并显示不同的错误消息。
尝试取消注释@PostConstruct中的代码,然后再次运行应用程序。
```java
@PostConstruct
public void postConstruct() {
for (QuestionType type : QuestionType.values()) {
numberOfQuestionsByType.put(type, 
questionService.findByQuestionType(type).size());
}
}
英文:

The error-message states that when creating the bean it has troubles with your datasource:

InvalidDataAccessResourceUsageException: could not extract ResultSet

I suspect a problem when reading the database. There is no circular dependency issue. It is a perfect bean-creation chain. Spring detects a circular dependency and shows a diffrent error message.

Try to uncomment the code in the @PostConstruct and run the application again.

@PostConstruct
public void postConstruct() {
for (QuestionType type : QuestionType.values()) {
numberOfQuestionsByType.put(type, 
questionService.findByQuestionType(type).size());
}
}

答案2

得分: 1

堆栈跟踪很直接,AssessmentServiceImplAssessmentService 的 bean 创建失败,因为出现了 SQL SQLGrammarException

嵌套异常是 org.hibernate.exception.SQLGrammarException: 无法提取结果集

这意味着 Hibernate 在执行您在 bean 后置构造中提供的查询时出现问题。很可能是这段代码引发了问题:questionService.findByQuestionType(type).size()。请分析日志以确认或共享完整的日志。

检查 Entity 类,确保一切都正确映射,并且所有注释都正确提供。尝试启用 Hibernate 日志以获得更详细的日志以进行分析。

英文:

The stacktrace is pretty straight forward , your bean creation of AssessmentService in AssessmentServiceImpl is failing because of sql SQLGrammarException:

nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet

which means that hibernate is having issues executing the query that you provided in your bean post construct.
Most probably this code : questionService.findByQuestionType(type).size() is causing the issue for you during bean creation. Analyse the logs more to confirm or share the full logs.

Check the Entity class to ensure everything is mapped correctly and all the annotations are provided correctly. Try enabling the hibernate logs for more detailed log for analysis.

答案3

得分: 0

问题是,您正试图从数据库中获取一些响应,放入一个结果集中。查询并不返回整个对象,而是仅返回对象的一部分或两个或更多类的组合。您的Hibernate类没有相匹配的构造函数,因此无法初始化您的对象。

英文:

The problem is, you are trying to fetch some response from the DB, into a resultset. The query does not return the entire object, instead only a part of the object or combination of two or more classes. Your hibernate class does not have the matching constructor, thus it is unable to initialize your object.

答案4

得分: 0

谢谢所有的评论,它把我带回了正确的轨道。
问题出在Hibernate设置中:

hibernate:
ddl-auto: none

所以我把它改成了:

hibernate:
ddl-auto: create

现在它可以工作了。

英文:

Thank for all the comments, it brought me back to the right track.
Problem was in hibernate settings:

hibernate:
ddl-auto: none

so I changed it to:

hibernate:
ddl-auto: create

and it works now.

huangapple
  • 本文由 发表于 2020年7月28日 16:56:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/63130463.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定