【问题标题】:Select specific columns in JPA Spring Boot在 JPA Spring Boot 中选择特定列
【发布时间】:2021-08-17 14:39:14
【问题描述】:

我想从我的表中获取一些特定的列,但是我收到了这个错误: 无法执行查询; SQL [SELECT name, image FROM characters order by name asc];嵌套异常是 org.hibernate.exception.SQLGrammarException: could not execute query。

o.h.engine.jdbc.spi.SqlExceptionHelper:SQL 错误:0,SQLState:42703 o.h.engine.jdbc.spi.SqlExceptionHelper : 在这个 ResultSet 中找不到列名 id。

我想运行这个查询:

public interface CharacterRepository extends JpaRepository<CharacterEntity, Long> {
    @Query(value = "SELECT name, image FROM characters", countQuery = "SELECT COUNT(name) FROM characters", nativeQuery = true)
    Page<CharacterEntity> getCharacters(Pageable pageable);
}

我的实体类:

@Entity(name = "characters")
@Getter @Setter
public class CharacterEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private long id;

    @Column(nullable = false)
    private String image;

    @Column(nullable = false, length = 100)
    private String name;

    @Column(nullable = false)
    private Integer age;

    @Digits(integer = 8, fraction = 2)
    private BigDecimal weight;

    private String story;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "character")
    private List<MovieDetailEntity> movies;

}

我的 Dto 课程:

@Getter @Setter
public class CharacterDto implements Serializable {

    private static final long serialVersionUID = 1L;

    private long id;
    private String image;
    private String name;
    private Integer age;
    private BigDecimal weight;
    private String story;
    private List<MovieDetailDto> movies;

    public CharacterDto() {

    }
    public CharacterDto(long id, String image, String name, Integer age, BigDecimal weight, String story) {
        this.id = id;
        this.image = image;
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.story = story;
    }
}

【问题讨论】:

    标签: java spring-boot hibernate spring-data-jpa


    【解决方案1】:

    您可以将返回类型更改为 Page

    @Query(value = "SELECT name, image FROM characters", countQuery = "SELECT COUNT(name) FROM characters", nativeQuery = true)
    Page<Object[]> getCharacters(Pageable pageable);
    

    【讨论】:

      【解决方案2】:

      如果您想选择自定义列,您将创建一个自定义 dto 并将数据加载到其中。您无法将自定义数据加载到托管实体中,但您可以使用 jpql 选择到您的自定义 dto。

      package my.class.package;
      
      class Chars{
          private String name;
          private IDONTKNOW image;  
          [other fields, constructors, getters,setters ...]
      }
      

      然后就可以查询进去了:

      @Query("SELECT new my.class.package.Chars(c.name,c.image) FROM characters c")
      Page<Chars> getCharacters(Pageable pageable);
      

      您还可以使用此类查询通过加入这些查询来加载来自不同表(实体)的字段。

      例如(我以前的一个,但也许它会帮助你):

         public class ProgrammerNameAndCity {
             private String name;
             private String city;
         }
          
          @Entity
          @Table(name = "programmer")
          public class Programmer extends BaseEntity {
          
              @Basic
              private String name;
          
              @Column(name = "id_number", nullable = false, unique = true)
              private String idNumber;
          
              //hibernate specific
              @Type(type = "yes_no")
              private Boolean senior;
          
              @Basic
              private Integer salary;
          
              @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
              @JoinColumn(name = "address_id")
              private Address address;
          
          }
          
          @Entity
          @Table
          public class Address extends BaseEntity {
          
              @Basic
              private Integer zip;
          
              @Basic
              private String city;
          
              @Basic
              private String street;
          
              @Column(name = "house_number")
              private Integer houseNumber;
          
              @OneToOne(mappedBy = "address")
              private Programmer programmer;
          
          }
          
         @Query("select new mypackage.ProgrammerNameAndCity(p.name,p.address.city) from Programmer p where  p.idNumber=?1")
         ProgrammerNameAndCity findNameAndCityByIdNumber(String idNumber);
      

      【讨论】:

      • 它仍然不起作用,编辑问题以便您看到我的 Dto 课程。我有这个错误:无法在类 [alkemy.challenge.dtos.CharacterDto] 上找到适当的构造函数。预期的参数是:java.lang.String, java.lang.String [SELECT new alkemy.challenge.dtos.CharacterDto(c.name,c.image) FROM alkemy.challenge.entities.CharacterEntity c]
      • 这是因为您只有两个构造函数,空字段和所有字段,如果您只想从查询中设置这两个字段,您还必须创建一个包含这两个字段的构造函数,例如 `public CharacterDto (字符串名称,字符串图像){ this.name=name;这个.图像=图像; } `
      【解决方案3】:

      我认为这是Blaze-Persistence Entity Views 的完美用例。

      我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

      使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

      @EntityView(CharacterEntity.class)
      public interface CharacterImageDto {
          @IdMapping
          Long getId();
          String getImage();
      }
      

      查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

      CharacterImageDto a = entityViewManager.find(entityManager, CharacterImageDto.class, id);

      Spring Data 集成让您可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

      Page<CharacterImageDto> findAll(Pageable pageable);
      

      最好的部分是,它只会获取实际需要的状态! Blaze-Persistence Entity-Views 也支持映射集合,例如

      @EntityView(CharacterEntity.class)
      public interface CharacterDto {
          @IdMapping
          Long getId();
          String getImage();
          Set<MovieDto> getMovies();
      
          @EntityView(MovieDetailEntity.class)
          interface MovieDto {
              @IdMapping
              Long getId();
              String getName();
          }
      }
      

      【讨论】:

      • 对不起,我应该如何在 Spring Boot 中配置库,我应该制作一个 Blaze-Persistence bean 吗?我刚刚开始接触java spring boot的世界,我才意识到你是图书馆的创造者,我一直在阅读,它很棒,问候
      猜你喜欢
      • 2014-03-27
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 2020-01-14
      • 2020-03-03
      相关资源
      最近更新 更多