Static Factory Method in JPQL query instead of constructor

Hop*_*ing 6 java spring hibernate jpa jpql

Currently I use a lot of queries which use constructors for building value objects in JPQL as below

@Query("SELECT new com.DocDTO(d.documentId, d.docType) FROM Document d where d.parentId=:parentId")
Set<DocDTO> getDocsWithinFolder(@Param("parentId") Long parentId);
Run Code Online (Sandbox Code Playgroud)

But as code gets complex, I have a need to build objects with various combinations of constructor parameters, leading to the classic telescoping problem.

As explained in Effective Java (Item1) is there a way to build a JPQL query by passing a factory method instead of a constructor ? I am thinking something along the lines of

  @Query("SELECT DocDTO.query1(d.documentId, d.docType) FROM Document d where d.parentId=:parentId")
    Set<DocDTO> getDocsWithinFolder(@Param("parentId") Long parentId);
Run Code Online (Sandbox Code Playgroud)

and then build the appropriate static factory method query1 inside the DocDTO class. Is this possible in JPQL ?

Aji*_*man 3

您可以使用Dynamic projection它来解决这个问题。动态投影允许您动态更改单个查询的返回类型。为了更好地理解这一点,让我们举一个 User 实体的例子:

    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Long id;
        private String firstName;
        private String lastName;
        private String email;
        // setter and getters
}
Run Code Online (Sandbox Code Playgroud)

如果您只想首先使用动态投影获取用户名,您将需要创建一个如下界面:

public interface Name {
      String getLastName();
      String getFirstName();
}
Run Code Online (Sandbox Code Playgroud)

在您的存储库中,您将需要创建如下查询:

<T> List<T> findByLastName(String lastName, Class<T> type);
Run Code Online (Sandbox Code Playgroud)

或与@Query

@Query("select u.firstName,u.lastName from User u where lastName=?1")
<T> List<T> findByLastName(String lastName,Class<T> type);
Run Code Online (Sandbox Code Playgroud)

为您服务:

List<Name> name = findByLastName("xyz",Name.class);
Run Code Online (Sandbox Code Playgroud)