spring 找不到能够从类型转换到类型的转换器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46083329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:29:56  来源:igfitidea点击:

No converter found capable of converting from type to type

springjpaspring-data-jpaconverter

提问by Menios

I am getting the following stacktrace:

我得到以下堆栈跟踪:

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [referencedata.ABDeadlineType] to type [referencedata.DeadlineType]
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:324)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:206)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:187)
    at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.convert(ResultProcessor.java:256)
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:201)
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:212)
    at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:149)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:121)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:483)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy143.findAllSummarizedBy(Unknown Source)
    at 

My classes are the following

我的课程如下

DeadlineType

截止日期类型

@Data
public class DeadlineType extends DefaultIdAndText {
    @Value("#{target.id}")
    String id;

    @Value("#{target.code}")
    String text;

    @Value("#{target.id}")
    public String getId() {
        return id;
    }

    @Value("#{target.code}")
    public String getText() {
        return text;
    }

}

ABDeadlineType

AB截止日期类型

@Data
@Entity
@Table(name = "deadline_type")
@AllArgsConstructor
@NoArgsConstructor
public class ABDeadlineType {

    private @Id
    String id;
    private String code;
}

DefaultIdAndText

默认标识和文本

@Data @AllArgsConstructor
@NoArgsConstructor
public class DefaultIdAndText implements IdAndText {

    public DefaultIdAndText(IdAndText idAndText){
        this.id = idAndText.getId();
        this.text = idAndText.getText();
    }

    @NotEmpty String id;
    String text;
}

DeadlineTypeRepository

截止日期类型存储库

public interface DeadlineTypeRepository extends JpaRepository<ABDeadlineType, Long> {
    List<DeadlineType> findAllSummarizedBy();
}

Update

更新

Could it be an issue that the projection/mapping using @Value("#{target.id}")format, does not work correctly because these have been done on a class and not on an interface???

使用@Value("#{target.id}")格式的投影/映射无法正常工作是否可能是一个问题,因为这些是在类上而不是在接口上完成的???

回答by Nick Savenia

Return ABDeadlineTypefrom repository:

ABDeadlineType从存储库返回:

public interface ABDeadlineTypeRepository extends JpaRepository<ABDeadlineType, Long> {
    List<ABDeadlineType> findAllSummarizedBy();
}

and then convert to DeadlineType. Manually or use mapstruct.

然后转换为 DeadlineType。手动或使用 mapstruct。

Or call constructor from @Queryannotation:

或者从@Query注解调用构造函数:

public interface DeadlineTypeRepository extends JpaRepository<ABDeadlineType, Long> {

    @Query("select new package.DeadlineType(a.id, a.code) from ABDeadlineType a ")
    List<DeadlineType> findAllSummarizedBy();
}

Or use @Projection:

或使用@Projection

@Projection(name = "deadline", types = { ABDeadlineType.class })
public interface DeadlineType {

    @Value("#{target.id}")
    String getId();

    @Value("#{target.code}")
    String getText();

}

Update:Spring can work without @Projectionannotation:

更新:Spring 可以在没有@Projection注释的情况下工作:

public interface DeadlineType {
    String getId();    
    String getText();
}

回答by Les Wilson

You may already have this working, but the I created a test project with the classes below allowing you to retrieve the data into an entity, projection or dto.

您可能已经有了这个工作,但是我使用下面的类创建了一个测试项目,允许您将数据检索到实体、投影或 dto 中。

Projection- this will return the code column twice, once named code and also named text (for example only). As you say above, you don't need the @Projection annotation

投影- 这将返回代码列两次,一次命名为代码,也命名为文本(仅作为示例)。正如你上面所说,你不需要@Projection 注释

import org.springframework.beans.factory.annotation.Value;

public interface DeadlineTypeProjection {
    String getId();

    // can get code and or change name of getter below
    String getCode();

    // Points to the code attribute of entity class
    @Value(value = "#{target.code}")
    String getText();
}

DTO class- not sure why this was inheriting from your base class and then redefining the attributes. JsonProperty just an example of how you'd change the name of the field passed back to a REST end point

DTO 类- 不知道为什么这是从您的基类继承然后重新定义属性。JsonProperty 只是一个示例,说明如何更改传递回 REST 端点的字段名称

import com.fasterxml.Hymanson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class DeadlineType {
    String id;

    // Use this annotation if you need to change the name of the property that is passed back from controller
    // Needs to be called code to be used in Repository
    @JsonProperty(value = "text")
    String code;

}

Entity class

实体类

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Data
@Entity
@Table(name = "deadline_type")
public class ABDeadlineType {

    @Id
    private String id;
    private String code;
}

Repository- your repository extends JpaRepository<ABDeadlineType, Long> but the Id is a String, so updated below to JpaRepository<ABDeadlineType, String>

存储库- 您的存储库扩展 JpaRepository<ABDeadlineType, Long> 但 Id 是一个字符串,因此在下面更新为 JpaRepository<ABDeadlineType, String>

import com.example.demo.entity.ABDeadlineType;
import com.example.demo.projection.DeadlineTypeProjection;
import com.example.demo.transfer.DeadlineType;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ABDeadlineTypeRepository extends JpaRepository<ABDeadlineType, String> {

    List<ABDeadlineType> findAll();

    List<DeadlineType> findAllDtoBy();

    List<DeadlineTypeProjection> findAllProjectionBy();

}

Example Controller- accesses the repository directly to simplify code

Example Controller- 直接访问存储库以简化代码

@RequestMapping(value = "deadlinetype")
@RestController
public class DeadlineTypeController {

    private final ABDeadlineTypeRepository abDeadlineTypeRepository;

    @Autowired
    public DeadlineTypeController(ABDeadlineTypeRepository abDeadlineTypeRepository) {
        this.abDeadlineTypeRepository = abDeadlineTypeRepository;
    }

    @GetMapping(value = "/list")
    public ResponseEntity<List<ABDeadlineType>> list() {

        List<ABDeadlineType> types = abDeadlineTypeRepository.findAll();
        return ResponseEntity.ok(types);
    }

    @GetMapping(value = "/listdto")
    public ResponseEntity<List<DeadlineType>> listDto() {

        List<DeadlineType> types = abDeadlineTypeRepository.findAllDtoBy();
        return ResponseEntity.ok(types);
    }

    @GetMapping(value = "/listprojection")
    public ResponseEntity<List<DeadlineTypeProjection>> listProjection() {

        List<DeadlineTypeProjection> types = abDeadlineTypeRepository.findAllProjectionBy();
        return ResponseEntity.ok(types);
    }
}

Hope that helps

希望有帮助

Les

莱斯

回答by Sangam Belose

If you look at the exception stack trace it says that, it failed to convert from ABDeadlineTypeto DeadlineType. Because your repository is going to return you the objects of ABDeadlineType. How the spring-data-jpawill convert into the other one(DeadlineType). You should return the same type from repository and then have some intermediate util class to convert it into your model class.

如果您查看异常堆栈跟踪,它说,它无法从 转换ABDeadlineTypeDeadlineType。因为您的存储库将返回ABDeadlineType. 将如何spring-data-jpa转换为另一个(DeadlineType)。您应该从存储库返回相同的类型,然后使用一些中间 util 类将其转换为您的模型类。

public interface ABDeadlineTypeRepository extends JpaRepository<ABDeadlineType, Long> {
    List<ABDeadlineType> findAllSummarizedBy();
}