【问题标题】:Return a DTO Object in spring data repository method annotated with @Query在使用 @Query 注释的 Spring 数据存储库方法中返回 DTO 对象
【发布时间】:2019-03-25 17:07:01
【问题描述】:

我有一个存储库,在这个界面中我有一个方法想要返回一个 ComentarioEditalDto 而不是一个 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);

}

我删除了 Gets 和 Sets

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;

}

我删除了获取和设置

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

有一点例外

org.springframework.core.convert.ConverterNotFoundException: 否 发现能够从类型转换的转换器 [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] 在以下位置键入 [br.edu.ifrn.rederenova.dto.CommentarioEditalDto] 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]

【问题讨论】:

    标签: postgresql spring-boot jpa spring-data-jpa


    【解决方案1】:

    您需要在@Query 中返回一个 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 用作SELECT new br.edu.ifrn.rederenova.dto.ComentarioEditalDto
    • 在您的ComentarioEditalDto 中定义一个构造函数,其参数与您传递给SELECT new br.edu.ifrn.rederenova.dto.ComentarioEditalDto 的参数相同

    【讨论】:

    • 如何使用此解决方案创建我的 DTO 页面?
    【解决方案2】:

    首先不要删除 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);
    }
    

    存储库实现:

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

    【讨论】:

      【解决方案3】:

      只需将类 ComentarioEditalDto 更改为接口,如下所示:

      public interface ComentarioEditalDto {
      
          BigInteger getId();
          String getTexto();
          Calendar getDataCriacao();
          Calendar getDataUltimaEdicao();
          List<ComentarioEdital> getRespostasComentario(); --> attention to this ComentarioEdital
          Usuario getAutor();
          Edital getEdital();
          Boolean isExcluida();
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-18
        • 2021-05-31
        • 1970-01-01
        • 1970-01-01
        • 2011-07-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多