Grails CriteriaBuilder 添加限制
Grails CriteriaBuilder add Restrictions
我想创建我的条件对象并根据其他一些属性添加一些限制。
我试过类似的东西...
long from, to;
use(TimeCategory) {
from = (1.month.ago).getTime() / 1000L
to = (new Date()).getTime() / 1000L
}
def crit = Map.createCriteria()
// set date range
crit.between("appear", from, to)
// if testParam1 is present
if (params.testParam1 && !(params.testParam1.equals("all") || params.testParam1.isEmpty())) {
crit.eq("test1", testParam1)
}
// if testParam2 is present
if (params.testParam2 && !(params.testParam2.equals("all") || params.testParam2.isEmpty())) {
crit.eq("test2", testParam2)
}
但每次我得到 java.lang.IllegalArgumentException
此异常来自 HibernateCriteriaBuilder class,其中 validateSimpleExpression 测试失败
/**
* Creates a "between" Criterion based on the property name and specified lo and hi values
* @param propertyName The property name
* @param lo The low value
* @param hi The high value
* @return A Criterion instance
*/
public Object between(String propertyName, Object lo, Object hi) {
if(!validateSimpleExpression()) {
throwRuntimeException( new IllegalArgumentException("Call to [between] with propertyName ["+propertyName+"] not allowed here."));
}
propertyName = calculatePropertyName(propertyName);
return addToCriteria(Restrictions.between(propertyName, lo, hi));
}
private boolean validateSimpleExpression() {
if(this.criteria == null) {
return false;
}
return true;
}
知道如何动态添加一些限制吗?
你必须使用 Closure 并在 criteria 中传递它,让我举个简单的例子:
def criteria = Map.createCriteria()
Closure closure = {builder ->
if(params.testParam1){
builder.eq("test1", testParam1)
}
if(params.testParam2){
builder.eq("test2", testParam2)
}
builder.beetwen("appear", from, to)
}
比:
def result = criteria.list(){
closure(criteria)
}
@RomanRomanovsky 的答案的替代方法是传递 Closure
,然后将 HibernateCriteriaBuilder
的委托分配给添加的闭包的 delegate
:
def additionalRestrictions = {
if(params.testParam1){
eq("test1", testParam1)
}
...
}
// usage
def result = criteria.list(){
additionalRestrictions.delegate = delegate
additionalRestrictions()
}
@RomanRomanovsky 的方式对我来说实际上是新的,我想我更喜欢它。需要注意的一件事是,使用 delegate
不需要任何前缀到闭包中的方法(eq、createAlias 等)。
谢谢两位的建议。它引导我走向正确的方向。这是我的最终方法
long from, to;
use(TimeCategory) {
from = (1.month.ago).getTime() / 1000L
to = (new Date()).getTime() / 1000L
}
def records = Map.withCriteria {
// set date range
between("appear", from, to)
// if testParam1 is present
if (params.testParam1 && !(params.testParam1.equals("all") || params.testParam1.isEmpty())) {
eq("test1", testParam1)
}
// if testParam2 is present
if (params.testParam2 && !(params.testParam2.equals("all") || params.testParam2.isEmpty())) {
eq("test2", testParam2)
}
}
总是可以使用 Hibernate 条件查询
Criteria criteria = sessionFactory.currentSession.createCriteria(Map.class)
.add(Restrictions.between('appear', from, to))
// if testParam1 is present
if (params.testParam1 && !(params.testParam1.equals("all") || params.testParam1.isEmpty())) {
criteria.add(Restrictions.eq("test1", testParam1))
}
我最终这样做是为了允许一个函数 return 一个标准,在使用之前由调用者扩充。
我想创建我的条件对象并根据其他一些属性添加一些限制。
我试过类似的东西...
long from, to;
use(TimeCategory) {
from = (1.month.ago).getTime() / 1000L
to = (new Date()).getTime() / 1000L
}
def crit = Map.createCriteria()
// set date range
crit.between("appear", from, to)
// if testParam1 is present
if (params.testParam1 && !(params.testParam1.equals("all") || params.testParam1.isEmpty())) {
crit.eq("test1", testParam1)
}
// if testParam2 is present
if (params.testParam2 && !(params.testParam2.equals("all") || params.testParam2.isEmpty())) {
crit.eq("test2", testParam2)
}
但每次我得到 java.lang.IllegalArgumentException
此异常来自 HibernateCriteriaBuilder class,其中 validateSimpleExpression 测试失败
/**
* Creates a "between" Criterion based on the property name and specified lo and hi values
* @param propertyName The property name
* @param lo The low value
* @param hi The high value
* @return A Criterion instance
*/
public Object between(String propertyName, Object lo, Object hi) {
if(!validateSimpleExpression()) {
throwRuntimeException( new IllegalArgumentException("Call to [between] with propertyName ["+propertyName+"] not allowed here."));
}
propertyName = calculatePropertyName(propertyName);
return addToCriteria(Restrictions.between(propertyName, lo, hi));
}
private boolean validateSimpleExpression() {
if(this.criteria == null) {
return false;
}
return true;
}
知道如何动态添加一些限制吗?
你必须使用 Closure 并在 criteria 中传递它,让我举个简单的例子:
def criteria = Map.createCriteria()
Closure closure = {builder ->
if(params.testParam1){
builder.eq("test1", testParam1)
}
if(params.testParam2){
builder.eq("test2", testParam2)
}
builder.beetwen("appear", from, to)
}
比:
def result = criteria.list(){
closure(criteria)
}
@RomanRomanovsky 的答案的替代方法是传递 Closure
,然后将 HibernateCriteriaBuilder
的委托分配给添加的闭包的 delegate
:
def additionalRestrictions = {
if(params.testParam1){
eq("test1", testParam1)
}
...
}
// usage
def result = criteria.list(){
additionalRestrictions.delegate = delegate
additionalRestrictions()
}
@RomanRomanovsky 的方式对我来说实际上是新的,我想我更喜欢它。需要注意的一件事是,使用 delegate
不需要任何前缀到闭包中的方法(eq、createAlias 等)。
谢谢两位的建议。它引导我走向正确的方向。这是我的最终方法
long from, to;
use(TimeCategory) {
from = (1.month.ago).getTime() / 1000L
to = (new Date()).getTime() / 1000L
}
def records = Map.withCriteria {
// set date range
between("appear", from, to)
// if testParam1 is present
if (params.testParam1 && !(params.testParam1.equals("all") || params.testParam1.isEmpty())) {
eq("test1", testParam1)
}
// if testParam2 is present
if (params.testParam2 && !(params.testParam2.equals("all") || params.testParam2.isEmpty())) {
eq("test2", testParam2)
}
}
总是可以使用 Hibernate 条件查询
Criteria criteria = sessionFactory.currentSession.createCriteria(Map.class)
.add(Restrictions.between('appear', from, to))
// if testParam1 is present
if (params.testParam1 && !(params.testParam1.equals("all") || params.testParam1.isEmpty())) {
criteria.add(Restrictions.eq("test1", testParam1))
}
我最终这样做是为了允许一个函数 return 一个标准,在使用之前由调用者扩充。