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