Spring JPA 只返回字段,不返回实体

Spring JPA returning only fields, not entities

我有一个带有查询注释的 Spring JPA 存储库,如下所示:

@Repository
public interface MainRepository 
extends 
    JpaRepository<MainEntity, MainEntity.ID>, 
    JpaSpecificationExecutor<MainEntity> {

    @Query("select e.start, e.finish,e.forename,e.surname from MainEntity e where e.volunteerId= :id "
        + "and e.areaId>0 and e.isAssignment=true order by e.start")
    List<MainEntity> findAssignments(@Param("id") int volunteerId);
}

这不是 returnMainEntity 对象的列表,尽管 return 类型。它正在 returning 一个对象列表 [] 对应于请求的字段类型。

怎么回事???

这样写:

 @Query("from MainEntity e where e.volunteerId= :id "
        + "and e.areaId>0 and e.isAssignment=true order by e.start")

您请求的不是实体,而是实体的字段。而对象数组返回。 试试看:.

      Select e from MainEntity e ...

根据定义,当查询 return 一个具有 投影 的列表时,JPA 将 return 一个 Object[] 的列表,即,来自一个实体(或多个实体)的一组字段。

使用 Spring Data JPA,您可以通过定义如下接口,以 更优雅的格式 避免 Object[] 和 return 数据以下:

public interface MainEntityProjection {
    String getStart();
    String getFinish();
    String getForename();
    String getSurname();
}

并将您的查询方法更改为 return 上面定义的接口:

@Query("SELECT e.start, e.finish, e.forename, e.surname " +
       "FROM MainEntity e " +
       "WHERE e.volunteerId = :id AND e.areaId > 0 AND e.isAssignment = true " +
       "ORDER BY e.start")
List<MainEntityProjection> findAssignments(@Param("id") int volunteerId);

此方法在 Spring Data JPA documentation 中有描述。


除了 Spring Data JPA 之外,JPA 本身使用 SELECT NEW 使用 public 构造函数处理它。您可以定义 class 如下:

public class MainEntityProjection {

    private String start;
    private String finish;
    private String forename;
    private String surname;

    public MainEntityProjection(String start, String finish,
                                String forename, String surname) {
        this.start = start;   
        this.finish = finish;
        this.forename = forename;
        this.surname = surname;
    }

    // Getters and setters
}

然后你的查询将是这样的:

SELECT NEW org.example.MainEntityProjection(e.start, e.finish, e.forename, e.surname)
FROM MainEntity e
WHERE e.volunteerId = :id AND e.areaId > 0 AND e.isAssignment = true
ORDER BY e.start

以上查询也有望与 Spring Data JPA 一起使用(您的方法将 return 然后是 MainEntityProjection 的列表)。

查看定义 JPA 2.1 的文档 JSR 338 关于使用 SELECT NEW 和构造函数表达式的说明:

4.8.2 Constructor Expressions in the SELECT Clause

A constructor may be used in the SELECT list to return an instance of a Java class. The specified class is not required to be an entity or to be mapped to the database. The constructor name must be fully qualified.

If an entity class name is specified as the constructor name in the SELECT NEW clause, the resulting entity instances will be in either the new or the detached state, depending on whether a primary key is retrieved for the constructed object.

If a single_valued_path_expression or identification_variable that is an argument to the constructor references an entity, the resulting entity instance referenced by that single_valued_path_expression or identification_variable will be in the managed state.

For example,

SELECT NEW com.acme.example.CustomerDetails(c.id, c.status, o.count)
FROM Customer c JOIN c.orders o
WHERE o.count > 100