2016-11-02 17 views
8

Tôi đang sử dụng dữ liệu mùa xuân, QueryDSL và MySQL.Viết truy vấnTruy vấn truy vấn vị ngữ cho truy vấn dựa trên quan hệ OneTany

Mục đích chính của câu hỏi là biết cách thực hiện truy vấn như vậy theo cách queryDSL. Ví dụ được đưa ra chỉ là một ví dụ đơn giản để đưa ra ý tưởng.

Ví dụ: có hai bảng Nhân viên và Chứng chỉ. Mối quan hệ giữa hai là ONE (Employee) để NHIỀU (Certificate)

Sau đây là bảng,

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

gì nên là vị QueryDSL cho

Trở tất cả các nhân viên có tên chứa (trong first_name và last_name) và từ kết quả đó có chứng nhận từ ngày 22-12-2014 đến 22-12-2015

Tôi đã thử nhưng không thể có được cách tôi có thể lặp qua từng chứng chỉ của mỗi nhân viên trong cách QueryDSL và danh sách trả về của nhân viên.

Phản hồi của bạn sẽ được đánh giá cao !!

EDIT

Sau đây là các thực thể,

@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

Xem câu trả lời của tôi cập nhật. SQL được tạo ra khá xấu xí nhưng có vẻ như nó hoạt động. –

Trả lời

6

Điều dễ nhất để làm là đảo ngược nó và truy vấn cho giấy chứng nhận đó là đơn giản và sau đó bạn có thể nhận được các nhân viên từ giấy chứng nhận trả lại.

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

Nếu bạn muốn truy vấn cho nhân viên sau đó thử những điều sau đây mà là chống lại QueryDSL phiên bản 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

Giải pháp này không hoạt động và ném theo ngoại lệ, org.springframework.dao.InvalidDataAccessApiUsageException: Đường dẫn không được khai báo 'chứng chỉ'. Thêm đường dẫn này làm nguồn cho truy vấn để có thể tham chiếu nó .; ngoại lệ lồng nhau là chứng chỉ java.lang.IllegalArgumentException: Undeclared path '. Thêm đường dẫn này làm nguồn cho truy vấn để có thể tham chiếu nó. –

+0

Như tôi lưu ý trong câu trả lời "Trong trường hợp không có bất kỳ mã nào tôi sẽ đề nghị rằng nó sẽ ** trông giống như **". Bạn sẽ cần phải làm cho nó phù hợp với ánh xạ thực thể của bạn như không có ai ở đây có thể nhìn thấy chúng. –

+0

Tôi đã thêm đối tượng.vui lòng xem phần chỉnh sửa câu hỏi. Xin vui lòng cho tôi biết nếu bạn cần thêm thông tin –

1

Vì đây đã được đăng với một thẻ MySQL, tôi sẽ trả lời các truy vấn mà bạn cần (đối với những người khác) và sau đó hy vọng bạn có thể tìm ra mã QueryDSL từ đó:

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

Từ dòng lệnh có đầu ra:

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) 

Xin lỗi, không quen với QueryDSL, do đó bạn sẽ cần sửa đổi mã của mình để phù hợp với truy vấn đó.

Đây là schema tôi sử dụng để kiểm tra điều này với:

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'); 
Các vấn đề liên quan