简体   繁体   English

QueryDSL中的查询谓词

[英]Query Predicate in QueryDSL

The environment is Java, Spring-boot, Hibernat, QueryDSL, MySQL. 环境是Java,Spring-boot,Hibernat,QueryDSL,MySQL。

I have table structure 我有表结构

Episode 插曲

+----+-------------+--------
| 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 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;

Person

+----+-----------+----------+
| 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;

So each episode has multiple people. 因此,每一集都有多个人。 And the join table is Episode_Person. 联接表是Episode_Person。

My UI has a datatable with a filter on each column: 我的UI有一个数据表,每列上都有一个过滤器:

在此处输入图片说明

The filtering already works on Event and Address. 过滤已在事件和地址上起作用。 And looks like this predicate in QueryDSL: 看起来像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);

How would I now add a 3rd predicate for case name where case name is constructed of the first two people returned in the collection of people against a episode? 现在,我要如何为案例名称添加第三个谓词,其中案例名称是根据某集中返回的人员集合中返回的前两个人构造的?

UPDATE UPDATE

For clarification the DTO thats backs the UI view contains the "casename" attribute. 为了澄清起见,支持UI视图的DTO包含“ casename”属性。 It is created in the service layer when Domain objects are converted to DTO: 域对象转换为DTO时,将在服务层中创建它:

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

Not easily unless you delegate some of the processing to the database. 除非您将某些处理委托给数据库,否则不容易。

If we can get the case_name property to be populated at the database tier rather than as a derived property in the application logic then the front-end code becomes trivial. 如果我们可以将case_name属性填充到数据库层,而不是作为应用程序逻辑中的派生属性填充,那么前端代码就变得微不足道了。

We can do this by means of a view. 我们可以通过视图来做到这一点。 The exact definition of this will depend on your database however the output would be something like this: 确切的定义将取决于您的数据库,但是输出将如下所示:

episode_summary_vw episode_summary_vw

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

For Oracle it looks like LISTAGG function is what you would want and for MySQL the GROUP_CONCAT functions. 对于Oracle来说, LISTAGG函数似乎是您想要的,而对于MySQL, GROUP_CONCAT函数。 In MySQL then I think this would look something like: 然后在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

Once we have a view then we can simply map the case_name to the Episode entity using the @SecondaryTable functionality of JPA: 一旦有了视图,我们就可以使用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;
}

You then filter and sort on the property as for any other field: 然后,您可以像对其他任何字段一样对属性进行过滤和排序:

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

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

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

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