2016-11-02 4 views
8

스프링 데이터, QueryDSL 및 MySQL을 사용하고 있습니다.oneTomany 관계 기반 쿼리에 대한 queryDSL 조건부 쿼리를 작성하십시오.

질문의 주요 목적은 queryDSL 방식으로 이러한 쿼리를 수행하는 방법을 알아야합니다. 주어진 예제는 아이디어를주는 간단한 예일뿐입니다.

예를 들어 Employee와 Certificate 테이블이 두 개 있습니다. 둘 사이의 관계는

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

은 무엇 FIRST_NAME에 (

이름으로 모든 직원을 반환하는 것이 포함에 대한 QueryDSL 술어해야한다, 많은 (인증서)에 ONE (직원)

있는 테이블 다음과 같다 last_name) 및 해당 날짜의 인증 날짜가 22-12-2014 22-12-2015

시도했지만 시도 할 수 없었습니다. 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)); 

직원을 쿼리하려면 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

이 솔루션은 작동하지 않고 다음 예외를 throw합니다. org.springframework.dao.InvalidDataAccessApiUsageException : 선언되지 않은 경로 'certificate'. 이 경로를 참조 할 수 있도록 쿼리의 소스로 추가하십시오.; 중첩 예외는 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');