web-dev-qa-db-fra.com

Aucun convertisseur trouvé capable de convertir d'un type à l'autre

Je reçois le stacktrace suivant:

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$1.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$1.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 

Mes cours sont les suivants

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

@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();
}

Mise à jour

Pourrait-il être un problème que la projection/mappage utilisant le format @Value("#{target.id}") ne fonctionne pas correctement car cela a été fait sur une classe et non sur une interface ???

20

Renvoie ABDeadlineType du référentiel:

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

et ensuite convertir à DeadlineType. Manuellement ou utilisez mapstruct.

Ou appelez le constructeur de @Query annotation:

public interface DeadlineTypeRepository extends JpaRepository<ABDeadlineType, Long> {

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

Ou utiliser @Projection:

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

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

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

}

pdate: Spring peut fonctionner sans @Projection annotation:

public interface DeadlineType {
    String getId();    
    String getText();
}
26
Nick Savenia

Cela fonctionne peut-être déjà, mais j’ai créé un projet de test avec les classes ci-dessous vous permettant de récupérer les données dans une entité, une projection ou un dto.

Projection - Ceci retournera la colonne de code deux fois, une fois le code nommé et le texte nommé (par exemple uniquement). Comme vous le dites ci-dessus, vous n'avez pas besoin de l'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();
}

classe DTO - vous ne savez pas pourquoi cela héritait de votre classe de base, puis redéfinissait les attributs. JsonProperty est juste un exemple de la façon dont vous changeriez le nom du champ retourné en REST end point

import com.fasterxml.jackson.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;

}

classe d'entité

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 - votre référentiel étend JpaRepository <ABDeadlineType, Long> mais l'ID est une chaîne, donc mise à jour ci-dessous pour 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();

}

Exemple Controller - accède directement au référentiel pour simplifier le code

@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);
    }
}

J'espère que ça t'as aidé

Les

2
Les Wilson

Si vous examinez la trace de la pile des exceptions, elle indique que la conversion de ABDeadlineType en DeadlineType a échoué. Parce que votre référentiel va vous retourner les objets de ABDeadlineType. Comment le spring-data-jpa sera converti dans l'autre (DeadlineType). Vous devez renvoyer le même type depuis le référentiel, puis une classe intermédiaire intermédiaire pour le convertir en classe de modèle.

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