2016-11-02 14 views
8

Używam danych sprężynowych, QueryDSL i MySQL.Zapisywanie kwerendy kwerendy DSL dla zapytania opartego na relacji jednaTomania

Głównym celem pytania jest wiedzieć, jak wykonać takie zapytanie w sposób queryDSL. Podany przykład jest tylko prostym przykładem, aby dać pomysł.

Załóżmy na przykład, że istnieją dwie tabele Pracownik i certyfikat. Relacja między nimi jest jeden (Employee) do wielu (certyfikat)

Poniżej znajdują się stoły,

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

Jaki powinien być orzecznikiem QueryDSL dla

Wracając wszystkim pracownikom nazwa zawiera (w first_name i last_name) i od tego wyniku, którego certyfikacja pomiędzy 22-12-2014 a 22-12-2015

Próbowałem, ale nie mogłem zobacz, jak mogę powtórzyć każdy certyfikat każdego pracownika w sposób QueryDSL i zwróć listę pracowników.

Twoja odpowiedź będzie bardzo ceniona !!

EDIT

Poniżej znajdują się podmioty,

@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

Zobacz moją zaktualizowaną odpowiedź. Wygenerowany SQL jest dość brzydki, ale wygląda na to, że działa. –

Odpowiedz

6

Najłatwiej zrobić to odwrócić i zapytać certyfikatów, który jest prosty i można wtedy dostać pracownika z zwróconych świadectw.

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

Jeśli chcesz zapytać o pracowników, spróbuj wykonać następujące czynności, które są sprzeczne z QueryDSL w wersji 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

To rozwiązanie nie działa i generuje następujący wyjątek, org.springframework.dao.InvalidDataAccessApiUsageException: Undeclared path 'certificate'. Dodaj tę ścieżkę jako źródło do zapytania, aby móc się do niej odwołać .; Zagnieżdżony wyjątek to java.lang.IllegalArgumentException: certyfikat niezadeklarowanej ścieżki. Dodaj tę ścieżkę jako źródło do zapytania, aby móc się do niej odwoływać. –

+0

Jak zauważam w odpowiedzi "W przypadku braku jakiegokolwiek kodu sugerowałbym, że ** wyglądałby jak **". Będziesz musiał dopasować go do mapowania jednostek, ponieważ nikt tutaj nie może ich zobaczyć. –

+0

Dodałem encje.zobacz część edycyjną pytania. Proszę dać mi znać, jeśli potrzebujesz więcej informacji –

1

Ponieważ ta została wysłana z tagiem MySQL, mam zamiar odpowiedzieć na zapytanie, czego potrzeba (dla innych), a następnie z nadzieją można dowiedzieć się, że kod QueryDSL od:

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

z wiersza poleceń z wyjściem:

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) 

Niestety, nie zna QueryDSL więc trzeba zmodyfikować kod, aby dopasować tę kwerendę.

Oto schemat kiedyś przetestować to z:

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