2014-05-20 62 views
7

我對SpringData使用QueryDSL。 我有表說,Employee和我已經創建實體類說,EmployeeEntity 我已經寫以下服務方法在QueryDSL中處理可選參數

public EmployeeEntity getEmployees(String firstName, String lastName) 
{ 
    QEmployeeEntity employee = QEmployeeEntity.employeeEntity; 
    BooleanExpression query = null; 
    if(firstName != null) 
    { 
     query = employee.firstName.eq(firstName); 
    } 
    if(lastName != null) 
    { 
     query = query.and(employee.lastName.eq(lastName)); // NPException if firstName is null as query will be NULL 
    } 
    return empployeeDAO.findAll(query); 
} 

如上我評論的NPException。如何使用QueryDSL獲取可選參數QueryDSL使用Spring Data?

謝謝:)

回答

21

BooleanBuilder可以用作布爾表達式動態生成器:

public EmployeeEntity getEmployees(String firstName, String lastName) { 
    QEmployeeEntity employee = QEmployeeEntity.employeeEntity; 
    BooleanBuilder where = new BooleanBuilder(); 
    if (firstName != null) { 
     where.and(employee.firstName.eq(firstName)); 
    } 
    if (lastName != null) { 
     where.and(employee.lastName.eq(lastName)); 
    } 
    return empployeeDAO.findAll(where); 
} 
+0

但如果我們加入?你能幫我嗎?http://stackoverflow.com/questions/24792778/dynamic-search-by-criteria – Youssef

2

這是Java的101實際上是:檢查null和初始化查詢,而不是串聯的謂詞。所以像這樣的helper方法可以做的伎倆:

private BooleanExpression createOrAnd(BooleanExpression left, BooleanExpression right) { 
    return left == null ? right : left.and(right); 
} 

然後,你可以簡單地做:

BooleanExpression query = null; 

if (firstName != null) { 
    query = createOrAnd(query, employee.firstName.eq(firstName)); 
} 

if (lastName != null) { 
    query = createOrAnd(query, employee.lastName.eq(lastName)); 
} 

… 

請注意,我用createOrAnd(…)即使是在第一條簡單的一致性,並沒有如果您決定在firstName之前添加新條款,請修改該代碼。

+1

你救了我的時間:) –

0

如果選中QueryDSL實施null

public BooleanExpression and(@Nullable Predicate right) { 
    right = (Predicate) ExpressionUtils.extract(right); 
    if (right != null) { 
     return BooleanOperation.create(Ops.AND, mixin, right); 
    } else { 
     return this; 
    } 
} 

按理說它是你想要的。

0

此基礎上,你需要,我會做到這一點

public List<EmployeeEntity> getEmployees(Optional<String> firstName, Optional<String> lastName) 
{ 
    BooleanExpression queryPredicate = QEmployeeEntity.employeeEntity.firstName.containsIgnoreCase(firstName.orElse("")).and(QEmployeeEntity.employeeEntity.lastName.containsIgnoreCase(lastName.orElse(""))); 
    return empployeeDAO.findAll(queryPredicate); 
} 

,首先你應該返回EmployeeEntityList什麼。其次,它能夠更好地使用可選的比,如果其null檢查,你可以通過從Java可選RequestParam的像這樣獲得8的Optional值:

@RequestMapping(value = "/query", method = RequestMethod.GET) 
public ModelAndView queryEmployee(@RequestParam(value = "firstName", required = false) Optional<String> firstName, @RequestParam(value = "lastName", required = false) Optional<String> lastName) 
{ 
     List<EmployeeEntity> result = getEmployees(firstName, lastName);  
      .... 
} 

而且很重要的是要使用containsIgnoreCase功能謂語:比典型的like更好導致其不區分大小寫。

在我看來,你應該使用一些方法是這樣的:

@Controller 
class UserController { 

    @Autowired UserRepository repository; 

    @RequestMapping(value = "/", method = RequestMethod.GET) 
    String index(Model model, @QuerydslPredicate(root = User.class) Predicate predicate,  
      Pageable pageable, @RequestParam MultiValueMap<String, String> parameters) { 

    model.addAttribute("users", repository.findAll(predicate, pageable)); 

    return "index"; 
    } 
} 

看看它在here

4

BooleanBuilder很好。你也可以把它包起來,爲了避免如果添加條件「可選」的方法:

例如,對於「和」你可以這樣寫:(Java的8個lambda表達式中使用)

public class WhereClauseBuilder implements Predicate, Cloneable 
{ 
    private BooleanBuilder delegate; 

    public WhereClauseBuilder() 
    { 
     this.delegate = new BooleanBuilder(); 
    } 

    public WhereClauseBuilder(Predicate pPredicate) 
    { 
     this.delegate = new BooleanBuilder(pPredicate); 
    } 

    public WhereClauseBuilder and(Predicate right) 
    { 
     return new WhereClauseBuilder(delegate.and(right)); 
    } 

    public <V> WhereClauseBuilder optionalAnd(@Nullable V pValue, LazyBooleanExpression pBooleanExpression) 
    { 
     return applyIfNotNull(pValue, this::and, pBooleanExpression); 
    } 

    private <V> WhereClauseBuilder applyIfNotNull(@Nullable V pValue, Function<Predicate, WhereClauseBuilder> pFunction, LazyBooleanExpression pBooleanExpression) 
    { 
     if (pValue != null) 
     { 
      return new WhereClauseBuilder(pFunction.apply(pBooleanExpression.get())); 
     } 

     return this; 
    } 
    } 

    @FunctionalInterface 
    public interface LazyBooleanExpression 
    { 
     BooleanExpression get(); 
    } 

然後使用會更清潔:

public EmployeeEntity getEmployees(String firstName, String lastName) { 
    QEmployeeEntity employee = QEmployeeEntity.employeeEntity; 

    return empployeeDAO.findAll 
    (
     new WhereClauseBuilder() 
      .optionalAnd(firstName,() -> employee.firstName.eq(firstName)) 
      .optionalAnd(lastName,() -> employee.lastName.eq(lastName)) 
    ); 
} 

很可能也使用JDK的可選類