2016-11-02 5 views
8

Ich verwende Spring-Daten, QueryDSL und MySQL.Anfrage queryDSL Prädikat für oneTomany Beziehung Abfrage schreiben

Das Hauptziel der Frage ist zu wissen, wie man eine solche Abfrage in QueryDSL Weg macht. Ein gegebenes Beispiel ist nur ein einfaches Beispiel, um eine Idee zu geben.

Sagen Sie zum Beispiel gibt es zwei Tabellen Mitarbeiter und Zertifikat. Die Beziehung zwischen beiden ist, ONE (Mitarbeiter) zu vielen (Zertifikat)

Tabellen Im Folgenden sind,

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

Was

mit Namen alle Mitarbeiter zurückkehrend enthält (in first_name das QueryDSL Prädikat für sein sollte und last_name) und von diesem Ergebnis, dessen Zertifizierung zwischen Datum 22-12-2014 bis 22-12-2015

Ich versuchte es, konnte aber nicht bekommen, wie ich über jedes Zertifikat jedes Angestellten in der QueryDSL Weise und der Rückkehrliste von Angestellten iterieren kann.

Ihre Antwort wird sehr geschätzt werden !!

EDIT

Im Folgenden sind die Einheiten,

@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

meine Antwort aktualisiert See. Das generierte SQL ist ziemlich hässlich, sieht aber so aus, als ob es funktioniert. –

Antwort

6

Die einfachste Sache zu tun ist, es und Abfrage für Zertifikate Reverse, die einfach ist und Sie können dann die Mitarbeiter aus den zurückgegebenen Zertifikate erhalten.

Wenn Sie nach Mitarbeitern abfragen möchten, versuchen Sie Folgendes, was gegen QueryDSL Version 4.1.3 ist.

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

Diese Lösung funktioniert nicht und löst die folgende Ausnahme aus: org.springframework.dao.InvalidDataAccessApiUsageException: Nicht deklarierter Pfad 'Zertifikat'. Fügen Sie diesen Pfad als Quelle zur Abfrage hinzu, damit er darauf verweisen kann. verschachtelte Ausnahme ist java.lang.IllegalArgumentException: Zertifikat des nicht deklarierten Pfads. Fügen Sie diesen Pfad als Quelle zur Abfrage hinzu, um auf sie verweisen zu können. –

+0

Wie ich in der Antwort notiere "In Ermangelung eines Codes würde ich vorschlagen, dass es etwas wie ** aussehen würde". Du musst es passend zu deinen Entity-Zuordnungen machen, da niemand hier auf der Karte sie sehen kann. –

+0

Ich habe Entitäten hinzugefügt.Bitte siehe Teil der Frage bearbeiten. Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen –

1

Da dies mit einer MySQL-Tag geschrieben wurde, werde ich die Abfrage, die Sie brauchen (für andere) beantworten und dann hoffentlich können Sie den QueryDSL Code aus, dass herauszufinden:

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%') 

von der Kommandozeile mit Ausgang:

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) 

Sorry, nicht vertraut mit QueryDSL, so dass Sie Ihren Code ändern müssen werden diese Abfrage übereinstimmen.

Hier ist das Schema habe ich dies zu testen mit:

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'); 
Verwandte Themen