简体   繁体   English

从 Criteria 中获取 WHERE 子句作为 HQL 字符串或:动态 WHERE 子句在选择中具有动态列

[英]Get WHERE clause as HQL string from Criteria or: Dynamic WHERE clause with dynamic columns in select

I want to build a filter search for my application.我想为我的应用程序构建过滤器搜索。 However, there are a few restrictions.但是,有一些限制。 I have to be able to dynamically add conditions as well as dynamically modify the columns and joins I want to fetch.我必须能够动态添加条件以及动态修改我想要获取的列和连接。

I have tried using a JPA Repository (from Spring Data) with Specifications, and it builds the WHERE clause as desired, however I have no control over what columns and what joins Hibernate issues to the DB.我曾尝试使用 JPA 存储库(来自 Spring Data)和规范,它根据需要构建 WHERE 子句,但是我无法控制哪些列以及哪些内容将 Hibernate 问题连接到数据库。

I have also tried using the Hibernate Criteria API with Projections.我还尝试将 Hibernate Criteria API 与 Projections 结合使用。 The issued Query was as desired and I had full control over the selected columns and joins, as well as the WHERE clause, however, the result transformation proved to be too troublesome for parsing nested objects (I tried using a custom result transformer, but to no avail, for a single level object, the default behaviour was fine).发出的查询符合要求,我可以完全控制选定的列和连接,以及 WHERE 子句,但是,结果转换被证明对于解析嵌套对象来说太麻烦了(我尝试使用自定义结果转换器,但无济于事,对于单层对象,默认行为很好)。

The "solution" I have for now is building the HQL string depending on the case.我现在的“解决方案”是根据情况构建 HQL 字符串。 However, I have written code for building WHERE clause and I was wondering if there is a way to reuse it (eg get the HQL string from the Predicates of Spring Specifications, or from the Hibernate Restrictions).但是,我已经编写了用于构建 WHERE 子句的代码,我想知道是否有一种方法可以重用它(例如,从 Spring 规范的谓词或 Hibernate Restrictions 中获取 HQL 字符串)。

Of course, if there is a better way to do all that, I would be thankful if you shared.当然,如果有更好的方法来做这一切,如果你能分享,我将不胜感激。

You need to use QueryDSL .您需要使用QueryDSL

Step 1: Add com.mysema.querydsl:querydsl-apt , com.mysema.querydsl:querydsl-core and com.mysema.querydsl:querydsl-jpa dependencies to your project.步骤 1:com.mysema.querydsl:querydsl-aptcom.mysema.querydsl:querydsl-corecom.mysema.querydsl:querydsl-jpa依赖项添加到您的项目中。

Step 2 : Add @QueryEntity annotation to entity classes on which you wish to run dynamic queries.第 2 步:将@QueryEntity注释添加到您希望运行动态查询的实体类。 If the queries will included nested classes, add the annotation to the nested entity classes as well.如果查询将包含嵌套类,也将注释添加到嵌套实体类。 An example below:下面是一个例子:

@Entity
@QueryEntity
@Table(name = "users")
public class User {
  @OneToMany
  private Address address;
}

@Entity
@QueryEntity
@Table(name = "address")
public class Address {
  @ManyToOne
  private Country country;
}

@Entity
@QueryEntity
@Table(name = "country")
public class Country { }

Step 3 : Run the com.mysema.maven:apt-maven-plugin Maven plugin during the process phase as follows:第三步:在process阶段运行com.mysema.maven:apt-maven-plugin Maven插件如下:

<build>
  <plugins>
    <plugin>
      <groupId>com.mysema.maven</groupId>
      <artifactId>apt-maven-plugin</artifactId>
      <version>1.1.1</version>
      <executions>
        <execution>
          <goals>
            <goal>process</goal>
          </goals>
          <configuration>
            <outputDirectory>target/generated-sources/java</outputDirectory>
            <processor>com.mysema.query.apt.QuerydslAnnotationProcessor</processor>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Step 4 : Change the Spring Data JPA repository interface to extend QueryDslPredicateExecutor as well.第 4 步:更改 Spring Data JPA 存储库接口以扩展QueryDslPredicateExecutor

interface UserRepository extends JpaRepository<User, Long>, QueryDslPredicateExecutor<User> {}

With this set up, the APT plugin will generate Q classes for every class annotated with QueryEntity .通过此设置,APT 插件将为每个用QueryEntity注释的类生成Q类。 You can then generate dynamic queries using these classes.然后,您可以使用这些类生成动态查询。 For example:例如:

QUser user = QUser.user;

BooleanExpression query = and(eq(user.active, Boolean.TRUE), eq(user.address.country.name, "Belgium"));

Collection<User> activeUsersFromBelgium = userRepository.findAll(query);

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

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