java - QueryDSL 中的查询谓词

标签 java jpa spring-data querydsl

环境为Java、Spring-boot、Hibernat、QueryDSL、MySQL。

我有表结构

剧集

+----+-------------+--------
| id | address_id  | eventno
+----+-------------+--------
|  5 |         27  | F123
|  6 |         30  | F456
|  7 |         45  | F789
+----+-------------+--------

@Entity
public class Episode {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotEmpty
private String eventno;
@ManyToOne(cascade = CascadeType.ALL)
private Address address;

Episode_Person

+----+--------------+--------------+------------+-----------+
| id | episode_role | primary_flag | episode_id | person_id |
+----+--------------+--------------+------------+-----------+
| 19 | Buyer        |              |          5 |         1 |
| 20 | Subject      |              |          5 |         2 |
| 23 | Witness      |              |          6 |         3 |
| 24 | Child        |              |          6 |         4 |
| 27 | Buyer        |              |          5 |         3 |
| 63 | Investor     |              |          5 |         4 |
| 64 | Subject      |              |          7 |         1 |
| 65 | Subject      |              |          7 |         3 |

@Entity
public class EpisodePerson {

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

@ManyToOne
@Valid
private Person person;

@ManyToOne
private Episode episode;

+----+-----------+----------+
| id | firstname | surname  |
+----+-----------+----------+
|  1 | Clint     | eastwood |
|  2 | Angelina  | joilee   |
|  3 | Brad      | pitt     |
|  4 | Jennifer  | aniston  |

@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"nia"}))
public class Person {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String surname;
private String firstname;
private String gender;

所以每一集都有多个人。连接表是 Episode_Person。

我的用户界面有一个数据表,每列都有一个过滤器:

enter image description here

过滤已适用于事件和地址。看起来像 QueryDSL 中的这个谓词:

            BooleanBuilder where = new BooleanBuilder();
        if (pagination.getFilterBy().getMapOfFilters().get("eventno")!=null) {
            where.and(qEpisode.eventno.containsIgnoreCase(pagination.getFilterBy().getMapOfFilters().get("eventno")));
        }
        if (pagination.getFilterBy().getMapOfFilters().get("address")!=null) {
            where.and(qEpisode.address.formattedAddress.containsIgnoreCase(pagination.getFilterBy().getMapOfFilters().get("address")));
        }
        where.and(qEpisode.creatingUser.eq(user));
        List<Episode> e = episodeRepository.findAll(where);

现在,我如何为案例名称添加第三个谓词,其中案例名称是由针对某一事件的人员集合中返回的前两个人构建的?

更新

为了澄清,支持 UI View 的 DTO 包含“casename”属性。它是在Domain对象转换为DTO时在服务层创建的:

episodeDashboard.setNames(episodePersonList.get(0).getPerson().getSurname().toUpperCase() +" & " +episodePersonList.get(1).getPerson().getSurname().toUpperCase());

最佳答案

这并不容易,除非您将一些处理委托(delegate)给数据库。

如果我们能够在数据库层填充 case_name 属性,而不是作为应用程序逻辑中的派生属性,那么前端代码就会变得微不足道。

我们可以通过 View 来做到这一点。其确切定义取决于您的数据库,但输出将如下所示:

episode_summary_vw

+------------+-------------------------+
| epsiode_id | case_name               |
+------------+-------------------------+
|  5         |        Eastwood & Joilee| 
|  6         |           Pitt & Aniston| 
|  7         |           Aniston & Pitt| 
+------------+-------------------------+

对于 Oracle 来说,LISTAGG 函数就是您想要的,而对于 MySQL 来说,GROUP_CONCAT 函数就是您想要的。在 MySQL 中,我认为这看起来像:

CREATE VIEW episode_summary_vw as
SELECT ep.episode_id, GROUP_CONCAT(p.surname SEPARATOR ' & ')
FROM episode_person ep
INNER JOIN person p on p.id = ep.person_id
GROUP BY ep.episode_id;
-- todo: needs limit to first 2 records

一旦我们有了 View ,我们就可以使用 JPA 的 @SecondaryTable 功能简单地将 case_name 映射到 Episode 实体:

@Entity
@Table(name = "episodes")
@SecondaryTable(name = "episode_summary_vw", primaryKeyJoinColumna = @PrimaryKeyJoinColumn(name="episode_id", reference_column_name="id"))
public class Episode {

    @Column(name ="case_name", table = "episode_summary_vw")
    private String caseName;
}

然后,您可以像对任何其他字段一样对属性进行过滤和排序:

if (pagination.getFilterBy().getMapOfFilters().get("caseName")!=null) {

    where.and(qEpisode.caseName.containsIgnoreCase(pagination.getFilterBy().
       getMapOfFilters().get("caseName")));
}

关于java - QueryDSL 中的查询谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47506187/

相关文章:

java - 在 Vert.x 应用程序中使用 Project Reactor

java - prepareStatement 为 getPassword 抛出错误

Java Order by 具有不同子对象类型的一对多关系

spring - 在单个Hadoop节点上连接Hadoop Jobfactorybean,多个Reducer

java - 正则表达式 - 使用正则表达式搜索字符串并从原始字符串中提取匹配项

java - MapReduceBase 和 Mapper 已弃用

java - JPA OneToOne 惰性关系

java - jpa 中生成的表中的顺序错误

java.sql.SQLException : ORA-00942: table or view does not exist with JPA entityManager. createQuery()

java - 如何保证 `Spring-Data`中的每一个数据库事务都按顺序执行?