Postgresql 在spring数据存储库方法中返回一个DTO对象,并用@Query注释

Postgresql 在spring数据存储库方法中返回一个DTO对象,并用@Query注释,postgresql,spring-boot,jpa,spring-data-jpa,Postgresql,Spring Boot,Jpa,Spring Data Jpa,我有一个存储库,在这个接口中,我有一个方法希望返回一个ComentarioEditalTo而不是一个ComentarioEdital,但是当我调用这个方法时,会抛出一个异常,告诉我我没有转换器,我如何转换以返回另一个类的实例 import br.edu.ifrn.rederenova.dto.ComentarioEditalDto; import br.edu.ifrn.rederenova.model.ComentarioEdital; import java.util.List; impor

我有一个存储库,在这个接口中,我有一个方法希望返回一个ComentarioEditalTo而不是一个ComentarioEdital,但是当我调用这个方法时,会抛出一个异常,告诉我我没有转换器,我如何转换以返回另一个类的实例

import br.edu.ifrn.rederenova.dto.ComentarioEditalDto;
import br.edu.ifrn.rederenova.model.ComentarioEdital;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface ComentarioRepository extends CrudRepository<ComentarioEdital, Long>{

    @Query(value = "SELECT c.id, c.texto, c.data_ultima_edicao, c.autor_id, " +
           "c.data_criacao, c.edital_id, c.excluida FROM comentario_edital c INNER JOIN edital e ON e.id = c.edital_id " +
           "WHERE (c.excluida = FALSE OR c.excluida IS NULL) AND e.numero = :numero ORDER BY c.data_criacao DESC",
            nativeQuery = true)
    public List<ComentarioEditalDto> findAllByEdital(@Param("numero") String nuEdital);

}
导入br.edu.ifrn.rederenova.dto.comentarioEditAlTo;
导入br.edu.ifrn.rederenova.model.ComentarioEdital;
导入java.util.List;
导入org.springframework.data.jpa.repository.Query;
导入org.springframework.data.repository.crudepository;
导入org.springframework.data.repository.query.Param;
导入org.springframework.stereotype.Repository;
@存储库
公共接口ComentarioRepository扩展了Crudepository{
@查询(value=“选择c.id、c.texto、c.data\u ltima\u edicao、c.autor\u id,”+
“c.data_criacao,c.edital_id,c.excluida FROM comentario_edital c internal JOIN edital e ON e.id=c.edital_id”+
“其中(c.excluida=FALSE或c.excluida为NULL)和e.numero=:按c.data\u criacao DESC的编号顺序”,
nativeQuery=true)
公共列表findAllByEdital(@Param(“numero”)字符串numedital);
}
我把所有的东西都搬走了

import br.edu.ifrn.rederenova.model.ComentarioEdital;
import br.edu.ifrn.rederenova.model.Edital;
import br.edu.ifrn.rederenova.model.Usuario;
import java.util.Calendar;
import java.util.List;

public class ComentarioEditalDto {

    private Long id;
    private String texto;
    private Calendar dataCriacao;
    private Calendar dataUltimaEdicao;
    private List<ComentarioEdital> respostasComentario;
    private Usuario autor;
    private Edital edital;
    private Boolean excluida;

}
导入br.edu.ifrn.rederenova.model.ComentarioEdital;
导入br.edu.ifrn.rederenova.model.Edital;
导入br.edu.ifrn.rederenova.model.Usuario;
导入java.util.Calendar;
导入java.util.List;
公共类ComentarioEditaldo{
私人长id;
私有字符串texto;
私人日历数据;
私人日历数据终端;
私人名单负责人;
私人Usuario autor;
私人编辑;
私有布尔排他;
}
我把所有的东西都搬走了

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;

@Entity
@SequenceGenerator(allocationSize = 1, initialValue = 1, name = "comentario_seq", sequenceName = "comentario_seq")
public class ComentarioEdital implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "comentario_seq")
    private Long id;
    @NotBlank(message = "Não deve estar vazio")
    private String texto;
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private Calendar dataCriacao;
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private Calendar dataUltimaEdicao;
    @OneToMany(cascade = {CascadeType.REMOVE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinTable(name = "respostas_comentario",
                joinColumns = @JoinColumn(name = "pergunta_id"),
                inverseJoinColumns = @JoinColumn(name = "resposta_id"))
    private List<ComentarioEdital> respostasComentario;
    @ManyToOne(fetch = FetchType.EAGER)
    private Usuario autor;
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    private Edital edital;
    @JsonIgnore
    private Boolean excluida;
}
import com.fasterxml.jackson.annotation.JsonIgnore;
导入java.io.Serializable;
导入java.util.Calendar;
导入java.util.List;
导入java.util.Objects;
导入javax.persistence.CascadeType;
导入javax.persistence.Entity;
导入javax.persistence.FetchType;
导入javax.persistence.GeneratedValue;
导入javax.persistence.GenerationType;
导入javax.persistence.Id;
导入javax.persistence.JoinColumn;
导入javax.persistence.JoinTable;
导入javax.persistence.manytone;
导入javax.persistence.OneToMany;
导入javax.persistence.SequenceGenerator;
导入javax.persistence.Temporal;
导入javax.persistence.TemporalType;
导入javax.validation.constraints.NotBlank;
导入org.springframework.format.annotation.DateTimeFormat;
@实体
@SequenceGenerator(allocationSize=1,initialValue=1,name=“comentario_-seq”,sequenceName=“comentario_-seq”)
公共类ComentarioEdital实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“comentario_seq”)
私人长id;
@NotBlank(message=“Não deve estar vazio”)
私有字符串texto;
@时态(TemporalType.TIMESTAMP)
@日期时间格式(pattern=“dd/MM/yyyy”)
私人日历数据;
@时态(TemporalType.TIMESTAMP)
@日期时间格式(pattern=“dd/MM/yyyy”)
私人日历数据终端;
@OneToMany(cascade={CascadeType.REMOVE,CascadeType.REFRESH},fetch=FetchType.EAGER)
@JoinTable(name=“respostas\u comentario”,
joinColumns=@JoinColumn(name=“pergunta_id”),
inverseJoinColumns=@JoinColumn(name=“resposta\u id”))
私人名单负责人;
@manytone(fetch=FetchType.EAGER)
私人Usuario autor;
@杰索尼奥雷
@manytone(fetch=FetchType.LAZY)
私人编辑;
@杰索尼奥雷
私有布尔排他;
}
有一点例外

org.springframework.core.convert.ConverterNotFoundException:否 发现转换器能够从类型转换 [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] 在以下位置键入[br.edu.ifrn.rederenova.dto.comentarioEditalTo] org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-5.0.7.RELEASE.jar:5.0.7.RELEASE]位于 org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) ~[spring-core-5.0.7.RELEASE.jar:5.0.7.RELEASE]


首先,不要删除POJO的getter/setter。 第二,如果您想从存储库返回自定义对象,我建议您使用QueryDSL。您可以这样使用它: 存储库:

@Repository
public interface EntityRepository extends JpaRepository<Entity, Long>, EntityRepositoryCustom, QuerydslPredicateExecutor<Entity> {
}
public interface EntityRepositoryCustom {
    List<EntityDTO> getEntityDTOsByCriteria(String arg0, String args1);
}
@存储库
公共接口EntityRepository扩展了JpaRepository、EntityRepositoryCustom、QueryDSL谓词执行器{
}
自定义存储库:

@Repository
public interface EntityRepository extends JpaRepository<Entity, Long>, EntityRepositoryCustom, QuerydslPredicateExecutor<Entity> {
}
public interface EntityRepositoryCustom {
    List<EntityDTO> getEntityDTOsByCriteria(String arg0, String args1);
}
公共接口实体位置自定义{
列出getEntityDTOsByCriteria(字符串arg0、字符串args1);
}
存储库impl:

public class EntityRepositoryImpl implements EntityRepositoryCustom {

    @Autowired
    private CardHolderRepository cardHolderRepository;

    @Autowired
    private EntityManager entityManager;

    @Override
    public List<EntityDTO> getEntityDTOsByCriteria(String arg0, String args1) {
    final List<EntityDTO> projections = new JPAQuery(entityManager, jpqlTemplates)
                    .from(entity)
                    .orderBy(entity.somefield.asc())
                    .list(ConstructorExpression.create(EntityDTO.class, entity.somefield,
                                    entity.someOtherfield));
    return projections;
}
public类EntityRepositoryImpl实现EntityRepositoryCustom{
@自动连线
私人持卡人储存库;
@自动连线
私人实体管理者实体管理者;
@凌驾
公共列表getEntityDTOsByCriteria(字符串arg0,字符串args1){
最终列表投影=新的JPAQuery(entityManager、jpqlTemplates)
.来自(实体)
.orderBy(entity.somefield.asc())
.list(ConstructorExpression.create(EntityDTO.class、entity.somefield、,
实体(someOtherfield));
回报预测;
}

您需要在
@查询中返回dto

@Query(value = "SELECT new br.edu.ifrn.rederenova.dto.ComentarioEditalDto(c.id, c.texto, c.dataCriacao, c.dataUltimaEdicao, c.excluida) " +
        "FROM ComentarioEdital c ....
  • 不要编写本机查询,您可以使用JPQL
  • 使用
    SELECT new package.DTOClass
    as
    SELECT new br.edu.ifrn.rederenova.dto.comentarioEditalTo
  • ComentarioEditalTo
    中,使用传递给
    的相同参数定义构造函数,并选择new br.edu.ifrn.rederenova.dto.ComentarioEditalTo

如何使用此解决方案创建我的DTO页面?