2016-11-02 22 views
8

我正在使用spring-data,QueryDSL和MySQL。爲一個基於Tomany關係的查詢寫入queryDSL謂詞查詢

問題的主要目的是要知道如何以queryDSL方式做這樣的查詢。給出的例子只是一個簡單的例子來給出想法。

舉例說,有兩張表Employee和Certificate。兩者之間的關係是(員工)許多(證書)

下面是桌子,

Employee (id, first_name, last_name); 
Certificate (id, name, date, fk_emp); 

應該是什麼

與名稱返回所有員工包含QueryDSL謂詞(在FIRST_NAME和last_name),並從那個結果的日期22日至2014年12月22日至2015年12月22日之間的認證

我試過了,但不能瞭解如何以QueryDSL方式遍歷每位員工的每個證書並返回員工列表。

您的迴應將非常感謝!

編輯

以下是實體,

@Entity 
@Table(name = "EMPLOYEE") 
class Employee { 
    @Id 
    @Column(name = "ID") 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 

    @Column(name = "FIRST_NAME") 
    private String firstName; 

    @Column(name = "LAST_NAME") 
    private String lastName; 

    @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL) 
    private List<Certificate> certificates = new ArrayList<>(); 
} 

@Entity 
@Table(name = "CERTIFICATE") 
class Certificate { 
    @Id 
    @Column(name = "ID") 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 

    @Column(name = "CERTIFICATE_NAME") 
    private String certificateName; 

    @Column(name = "DATE") 
    private Date date; 

    @ManyToOne 
    @JoinColumn(name = "REF_EMPLOYEE") 
    private Employee employee; 
} 
+0

看到我更新的答案。生成的SQL非常醜陋,但看起來像它的工作。 –

回答

6

做最簡單的事情是扭轉它和它是簡單的證書查詢,然後你可以從返回的證書的員工。

QCertificate certificate = QCertificate.certificate; 
BooleanExpression a = certificate.date.between(d1, d2); 
BooleanExpression b = certificate.employee.forename.eq("name"). 
     or(certificate.employee.surname.eq("name")); 

certificateRepository.findAll(a.and(b)); 

如果要查詢Employees,請嘗試以下與QueryDSL版本4.1.3相對的問題。

QEmployee employee = QEmployee.employee; 
    QCertificate certificate = QCertificate.certificate; 

    BooleanExpression a = employee.forename.eq("name").or(employee.surname.eq("name")); 

    BooleanExpression b = employee.certificates.contains(
     JPAExpressions.selectFrom(certificate). 
      where(certificate.employee.eq(employee). 
      and(certificate.date.between(d1, d2)))); 

    userRepository.findAll(a.and(b)); 
+0

此解決方案不起作用並拋出以下異常, org.springframework.dao.InvalidDataAccessApiUsageException:未聲明的路徑「證書」。將此路徑作爲源添加到查詢以便能夠引用它。嵌套異常是java.lang.IllegalArgumentException:未聲明的路徑'證書。將此路徑作爲源添加到查詢以便能夠引用它。 –

+0

正如我在回答中指出的那樣:「如果沒有任何代碼,我會建議它看起來像**」。你需要使它適合你的實體映射,因爲這裏沒有人能看到它們。 –

+0

我已添加實體。請參閱問題的編輯部分。如果您需要更多信息,請告知我 –

1

,因爲這是貼有一個MySQL標籤,我會回答你需要(替他人)查詢,然後希望你可以計算出從該QueryDSL代碼:

SELECT * from Certificate 
    WHERE date > "2014-01-01 00:00:00" and date < "2015-01-01 00:00:00" AND 
    id IN (SELECT id from Employee 
      WHERE first_name LIKE '%Name%' 
       || last_name LIKE '%LName%') 

從命令行輸出:

mysql> SELECT * from Certificate 
    ->   WHERE date > "2014-01-01 00:00:00" and date < "2015-01-01 00:00:00" AND 
    ->   id IN (SELECT id from Employee 
    ->    WHERE first_name LIKE '%Name%' 
    ->      || last_name LIKE '%LName%'); 
+----+--------------------+---------------------+--------+ 
| id | name    | date    | fk_emp | 
+----+--------------------+---------------------+--------+ 
| 1 | FirstName LastName | 2014-02-01 00:00:00 | 11111 | 
+----+--------------------+---------------------+--------+ 
1 row in set (0.00 sec) 

對不起,不熟悉QueryDSL,因此您需要修改您的代碼以匹配該查詢。

這是我使用來測試此模式:

CREATE TABLE `Certificate` (
    `id` int(11) NOT NULL, 
    `name` varchar(255) NOT NULL, 
    `date` datetime NOT NULL, 
    `fk_emp` int(11) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

INSERT INTO `Certificate` (`id`, `name`, `date`, `fk_emp`) VALUES 
(1, 'FirstName LastName', '2014-02-01 00:00:00', 11111); 

CREATE TABLE `Employee` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `first_name` varchar(255) NOT NULL, 
    `last_name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

INSERT INTO `Employee` (`id`, `first_name`, `last_name`) VALUES 
(1, 'FirstName', 'LastName');