当前位置: 首页 > 知识库问答 >
问题:

在Spring Data JPA中,如何通过分页按别名对SELECT子句中的投影进行排序?

程飞星
2023-03-14

我创建了这两个实体来证明我的问题:

业主ntity.java:

@Entity
public class OwnerEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Size(min = 1)
    @OneToMany(mappedBy = "ownerEntity", cascade = CascadeType.ALL)
    private Set<ChildEntity> childEntities = new HashSet<>();
}

子实体。java:

@Entity
public class ChildEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @NotNull
    @ManyToOne(optional = false)
    private OwnerEntity ownerEntity;

    public ChildEntity() {
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public OwnerEntity getOwnerEntity() {
        return ownerEntity;
    }

    public void setOwnerEntity(OwnerEntity ownerEntity) {
        this.ownerEntity = ownerEntity;
    }
}

我想写一个查询,显示来自OwnerEntity和一个连接的ChildEntity的信息。我创建了一个投影:

所有者权益项目。java:

public interface OwnerEntityProjection {

    Long getId();

    String getName();

}

我的JPA假设:

public interface OwnerEntityRepository extends JpaRepository<OwnerEntity, Long> {

    @Query(" SELECT                                        " +
           "       ownerEntity.id AS id,                   " +
           "       childEntities.name AS name              " +
           " FROM OwnerEntity ownerEntity                  " +
           " JOIN ownerEntity.childEntities childEntities  ")
    // There must be also WHERE clause, but for demonstration it is omitted
    Slice<OwnerEntityProjection> findAllPaginated(Pageable pageRequest);

}

现在,当我运行这个简单的测试时:

@Test
public void findAllPaginatedTest() {
    Pageable pageRequest = new PageRequest(0, 3, Sort.Direction.ASC, "name");
    Slice<OwnerEntityProjection> OwnerEntityProjectionsPaginated =
            ownerEntityRepository.findAllPaginated(pageRequest);
}

我收到以下错误:

org.hibernate.QueryException: could not resolve property: name of: com.example.domain.OwnerEntity

我还检查了日志中生成的JQPL:

... order by ownerEntity.name asc

如您所见,Spring Data Jpa从from子句中附加了第一个实体别名。我发现如果我将PageRequest更改为:

new PageRequest(0, 3, Sort.Direction.ASC, "childEntities.name");

它的工作原理没有错误,但我不想将排序属性传递给具有JPQL查询中某处别名的存储库。我想传递直接存在于存储库方法返回的投影中的属性。如果我在JPQL查询中手动编写ORDER BY,如下所示:

... ORDER BY name ASC

然后这个查询也可以正常运行,因为我可以从ORDER BY子句中引用SELECT子句中的别名。有没有什么方法可以告诉Spring Data Jpa在不附加from或JOIN子句别名的情况下执行排序?类似这样:

new PageRequest(0, 3, Sort.Direction.ASC, "name") ===> ORDER BY name asc

共有3个答案

冀俊良
2023-03-14
    String orderSort=page.getSort().toString();                
    Pageable page1 = 
    PageRequest.of(page.getPageNumber(),page.getPageSize(),
    JpaSort.unsafe(Sort.Direction.valueOf
    (orderSort.substring(page.getSort().toString().indexOf(':')+2,
    orderSort.length())),
    orderSort.substring(0,page.getSort().toString().indexOf(')')+1)));
涂承运
2023-03-14

在可分页控制器的切入点的上下文中,我将Dario Seidl的答案改编为以下内容:

public static Pageable parenthesisEncapsulation(final Pageable pageable) {

    Sort sort = Sort.by(Collections.emptyList());
    for (final Sort.Order order : pageable.getSort()) {
        if (order.getProperty().matches("^\\(.*\\)$")) {
            sort = sort.and(JpaSort.unsafe(order.getDirection(), order.getProperty()));
        } else {
            sort = sort.and(Sort.by(order.getDirection(), order.getProperty()));
        }
    }
    return PageRequest
        .of(pageable.getPageNumber(), pageable.getPageSize(), sort);
}

我可以这样给出控制器排序指令:

/myroute排序

司空瑾瑜
2023-03-14

这是Spring数据中的一个错误:未正确检测到别名。这里也有报道。

在applySorting方法的queryutil中,只检测到(外部)连接别名和正好有一对括号的函数别名。属性的简单别名当前不起作用。

一种解决方法是在构建PageRequest时使用JpaSort.unsafe,别名在括号中,例如。

PageRequest.of(0, 3, JpaSort.unsafe(Sort.Direction.ASC, "(name)"))

顾名思义,在根据用户输入动态排序时,这是不安全的,因此它应该只用于硬编码排序。

 类似资料:
  • 我的elasticsearch索引中有几千个文档。文档有几个嵌套集合。其中之一是“变体”的嵌套集合。JSON结构文档之一是: 我的商店在一页上只显示了48种产品。我的索引总共有4800种产品,所以在我的商店里有100页。 我对按价格排序有一个问题。 我编写了一些elasticsearch查询(用于第一页): 我有第一个48个产品与他们的变体,但这种排序工作不是在我的索引中的所有产品变体。这种排序的

  • 问题内容: 我有一个简单的选择查询- 我希望此结果按提供名称的顺序排序,也就是说,结果集中的第一行应该是名称= BBB的那一行,第二行是AAA,第三行是ZZZ。 在SQL Server中这可能吗?我想知道如果有一种简单且简短的方法(例如大约5到6行代码)来做到这一点。 问题答案: 您可以创建一个有序的拆分函数: 然后略微更改您的输入(一个逗号分隔的列表,而不是三个单独的字符串):

  • 问题内容: 我正在从具有整数id值的大型表(数百万行)中选择一组帐户记录。从某种意义上说,查询是最基本的。我正在做的是建立一个大型的逗号分隔列表,并将其作为“ in”子句传递到查询中。现在,结果是完全无序的。我想做的是按“ in”子句中的值顺序返回结果。 我想我将不得不建立一个临时表并进行联接,这是我想避免的,但可能无法做到。 有什么想法吗?现在,由于我们正试图限制输出大小,每个查询的大小上限为6

  • 问题内容: 我有一个使用IN子句的存储过程。在我的ASP.NET应用程序中,我有一个多行文本框,可为存储过程提供值。我希望能够按在文本框中输入的值进行排序。我发现如何在mySQL中轻松地执行此操作(使用FIELD函数),而不是与SQL Server等效的方法。 所以我的查询看起来像: 因此,我将从应用程序中传递值,例如‘113113’,‘112112’,‘114114’(以任意顺序)。我想按该列表

  • 我是Android Studio的新手,所以我面临一些问题。我正在寻找一种如何干净地项目的方法。 在Eclipse中,我会做<代码>项目-

  • 问题内容: 假设我有一张桌子,看起来像这样: 因此,每种电子邮件/电话组合都是唯一的,但是您可能会拥有多个电子邮件地址,这些电子邮件地址具有不同的电话号码,反之亦然。这有点做作,但它反映了我的情况。 我想做这样的查询: 但是,我想一次做多对,所以不必做几个查询。将两对保持在一起也很重要,因为我不想退回不需要的错误的电话/电子邮件组合。 我可以做这样的事情,但是对于数百个值的可能性,查询将非常长。