2014-07-16 2 views
2

QueryDSLSpring Data Jpa과 함께 사용하고 있으며 일부 동적 검색을 실행하고 싶습니다.조건에 의한 동적 검색

나는이 Answer을 따라 간다. BooleanBuilder과 오크가있다.하지만 내 경우에는 조인을해야한다.

player, player_team, team에 3 조인이 있는데 어떻게 할 수 있습니까? 플레이어 이름과 팀 이름에 대한 선택적 매개 변수가 있습니까? player.java

@Entity 
@Table(...) 
public class Player implements java.io.Serializable { 

    private Integer idPlayer ; 
    private String namePlayer; 
    private Set<PlayerTeam> player_teams = new HashSet<PlayerTeam>(0); 
    ... 
} 

team.java

@Entity 
@Table(...) 
public class Team implements java.io.Serializable { 

    private Integer idTeam ; 
    private String nameTeam; 
    private Set<PlayerTeam> player_teams = new HashSet<PlayerTeam>(0); 
    ... 
} 

player_team.java

@Entity 
@Table(...) 
public class PlayerTeam implements java.io.Serializable { 

    private Integer idPlayerTeam ; 
    private Team team; 
    private Player paleyr; 
    ... 
} 

각 도멘위한

________  ___________________  _______ 
| player | | player_team   | | team | 
|------ | |----------------  | |-------| 
| id  | | player_team_id (pk) | | id | 
| name | | player_id (fk)  | | name | 
    ------  | team_id (fk)  |  ------- 
       -----------  

그 같은 respository 있습니다

public interface PlayerRespository extends JpaRepository<Player, Integer>, QueryDslPredicateExecutor<Player> { 

} 
+0

어떻게 도메인 모델의 모습 않는 것입니까? –

+0

내 질문을 업데이트했습니다 – Youssef

+0

도메인 모델에 * 코드 *를 입력하십시오. 어떤 검색어? 무엇이 합류합니까? – philipxy

답변

0

Specification을 사용해 보셨습니까? Spring의 JPA 저장소 사양을 사용하여 결과를 찾기 위해이 방법이 있습니다

List<T> findAll(Specification<T> spec);

이 사양을 구축, 내 방식이 내 REST 서비스에서 요청을 수락에 맞게 조정되어 다른 접근 방법이있다, 그래서 나는 기본적으로 빈 개체를 만들 주어진 타입 (이 경우 Foo)과 요청 (예를 들어 이름)에 제공된 검색 기준을 설정 한 다음, 각 필드에서 술어를 작성합니다 (이름 필드가 지정된 경우 'name equals "bob"술어 추가). 당신이 PlayerTeam에 추가 속성을 넣지 않으면

import static org.springframework.data.jpa.domain.Specifications.where; 

import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 

import org.apache.commons.lang3.StringUtils; 
import org.springframework.data.jpa.domain.Specification; 

import com.acme.model.security.Principal; 

public class FooSpecification { 

    private final Foo criteria; 
    private String query; 

    public FooSpecification(String query, Foo criteria) { 
     this.query = query; 
     this.criteria = criteria; 
    } 

    public Specification<Foo> trainerEquals() { 
     if (criteria.getTrainer() == null) { 
      return null; 
     } 

     return new Specification<Foo>() { 

      @Override 
      public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       return cb.equal(root.<Principal>get("trainer").<Long>get("id"), criteria.getTrainer().getId()); 
      } 
     }; 
    } 

    public <T> Specification<Foo> valueEquals(final T value, final String field) { 
     if (value == null) { 
      return null; 
     } 

     return new Specification<Foo>() { 

      @Override 
      public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       return cb.equal(root.<T> get(field), value); 
      } 
     }; 
    } 

    /** 
    * Convert input string to lower case, appends '%' around it and does SQL LIKE comparison with the field value, also lower cased. 
    * If value is null, no comparison is done. Example: 
    * 
    * value = "John"; 
    * field = "firstName"; 
    * 
    * resulting specification = "name like '%john%'" 
    * 
    * @param value string or null 
    * @param field field name 
    * @return SQL LIKE specification for the given value or null if value is null 
    */ 
    public Specification<Foo> stringLike(final String value, final String field) { 
     if (StringUtils.isBlank(value)) { 
      return null; 
     } 

     return new Specification<Foo>() { 

      @Override 
      public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       return cb.like(cb.lower(root.<String> get(field)), getLikePattern(value)); 
      } 
     }; 
    } 

    private String getLikePattern(String searchTerm) { 
     return new StringBuilder("%") 
       .append(searchTerm.toLowerCase().replaceAll("\\*", "%")) 
       .append("%") 
       .toString(); 
    } 

    public Specification<Foo> fullSearch() { 
     return where(trainerEquals()) 
       .and(valueEquals(criteria.getName(), "name")) 
       .and(valueEquals(criteria.getInstructions(), "description")) 
       .and(valueEquals(criteria.isAwesome(), "isAwesome")) 
       .and(
        where(
          stringLike(query, "name")) 
         .or(stringLike(query, "instructions") 
        ) 
       ); 
    } 
} 
+0

질문은 '사양'이 아닌 'QueryDSL'에 관한 것입니다. –

1

이 엔티티로 모델링해서는 안 : 여기

은 사양 빌더의 예입니다. 조건에 관하여는

player.namePlayer.eq(...) 

new JPASubQuery().from(playerTeam) 
    .where(playerTeam.player.eq(player), palyerTeam.team.name.eq(...)) 
    .exists() 
+0

하지만 플레이어를 선택하고 PlayerTeam에 추가 필드가 있어야합니다. 왜 PlayerRespository가 아닌 JPASubQuery()를 사용하고 findall() 메서드를 사용합니까? – Youssef

+0

주어진 두 표현식은 findAll 메소드에 대한 인수이며, first.and (second) –

관련 문제