简体   繁体   English

JPA Spring 引导中的 Select 特定列

[英]Select specific columns in JPA Spring Boot

I want to get some specific columns from my table but I get this error: could not execute query;我想从我的表中获取一些特定的列,但我收到了这个错误:无法执行查询; SQL [SELECT name, image FROM characters order by name asc]; SQL [SELECT name, image FROM characters order by name asc]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query.嵌套异常是 org.hibernate.exception.SQLGrammarException:无法执行查询。

ohengine.jdbc.spi.SqlExceptionHelper: SQL Error: 0, SQLState: 42703 ohengine.jdbc.spi.SqlExceptionHelper: The column name id was not found in this ResultSet. ohengine.jdbc.spi.SqlExceptionHelper:SQL 错误:0,SQLState:42703 ohengine.jdbc.spi 在Sql ResultSetException 中找不到此列名:

I want to run this query:我想运行这个查询:

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

My entitiy class:我的实体 class:

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

}

My Dto class:我的 Dto class:

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

If you wanted to select custom colums, you would create a custom dto and load data into it.如果您想 select 自定义列,您将创建一个自定义 dto 并将数据加载到其中。 You cant load custom data into managed entities, but you can use jpql to select into your custom dto.您无法将自定义数据加载到托管实体中,但您可以使用 jpql 到 select 到您的自定义 dto 中。

package my.class.package;

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

Then you can query into it:然后你可以查询它:

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

You can also use this kind of queries to load fields from different tables (entities) by joining those.您还可以使用这种查询通过加入这些查询来加载来自不同表(实体)的字段。

For example (one of my old, but maybe it will help you):例如(我的一个老的,但也许它会帮助你):

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

Instead of returning Page you can change the return type to Page<Object[]>:您可以将返回类型更改为 Page<Object[]>,而不是返回 Page:

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

I think this is a perfect use case forBlaze-Persistence Entity Views .我认为这是Blaze-Persistence Entity Views的完美用例。

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids.我创建了该库以允许在 JPA 模型和自定义接口或抽象 class 定义的模型之间轻松映射,例如 Spring 类固醇上的数据投影。 The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.这个想法是您以您喜欢的方式定义您的目标结构(域模型),并通过 JPQL 表达式将 map 属性(吸气剂)定义为实体 model。

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:使用 Blaze-Persistence Entity-Views 的 DTO model 可能如下所示:

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

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

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

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features Spring 数据集成允许您几乎像 Spring 数据投影一样使用它: https://persistence.blazebit.com/documentation/entity-view/manual-html/。

Page<CharacterImageDto> findAll(Pageable pageable);

The best part is, it will only fetch the state that is actually necessary.最好的部分是,它只会获取实际需要的 state。 And Blaze-Persistence Entity-Views supports mapping collections as well eg Blaze-Persistence Entity-Views 也支持映射 collections,例如

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

    @EntityView(MovieDetailEntity.class)
    interface MovieDto {
        @IdMapping
        Long getId();
        String getName();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM