将varargs从Java代码传递给SQL或PL / SQL

时间:2011-08-31 16:45:29

标签: java sql oracle plsql jpa-2.0

我需要绑定最多8个变量。其中每一个都可以 null 。 有没有推荐的方法来实现这一目标?我知道我可以简单地检查 null ,但这看起来很乏味。

其他详情
我要从java代码中调用这个sql。它可以使用 JPA 2.0 Criteria API 编写,但很可能是原生查询。数据库是 Oracle 10g ,所以我想我也可以使用 PL / SQL

EDIT1:
也许标题有点误导,所以我会试着详细说明。 生成的SQL类似于:
...
WHERE var1 = :var1
AND var2 = :var2
...
AND var = :var8

现在我需要以类似的方式绑定java代码中的参数:
nativeQuery.setParameter("var1", var1)
...
nativeQuery.setParameter("var8", var8)

某些参数可能为null,因此无需绑定它们。但我认为我无法在SQL中省略它们。

EDIT2: 我期待在你的答案中看到SQL或PL / SQL程序(如果没有 null 检查就可以)。 实际上,所有这些变量都属于同一类型。我认为使用ANSI SQL找不到解决方案是不可能的,但也许有一些PL / SQL程序允许使用varargs?

2 个答案:

答案 0 :(得分:1)

在这种情况下,使用条件查询是合适的,因为如果我理解正确,您需要动态构造SQL查询。如果除var1之外的所有变量都为null,则where子句将为

where var1 = :var1

如果除var2和var5之外的所有变量都是非null,那么你将拥有

where var2 = :var2 and var5 = :var5

是吗?

如果是,则执行您打算执行的操作,并使用条件查询动态构造查询。必须这样做:

CriteriaBuilder builder = em.getCriteriaBuilder();
Predicate conjunction = builder.conjunction();
if (var1 != null) {
    conjunction = builder.and(conjunction,
                              builder.equal(root.get(MyEntity_.var1),
                                            var1));
}
if (var2 != null) {
    conjunction = builder.and(conjunction,
                              builder.equal(root.get(MyEntity_.var2),
                                            var2));
}
...
criteria.where(conjunction);

答案 1 :(得分:0)

您没有指定要传递的对象的类型。所以在这个例子中我认为你会传递对象

@Test(expected=IllegalArgumentException.class)
public void testMyMethod() {
    List<Object> testList = new ArrayList<Object>();
    testList.add("1");
    testList.add("2");
    testList.add(3);

    myMethod(testList);
}

public void myMethod(List<Object> limitedList) {
    final int MAX_SIZE = 2;
    if (limitedList.size() > MAX_SIZE) {
        throw new IllegalArgumentException("Size exceeded");
    }
    //my logic
}

在这个例子中,我将参数作为对象列表传递,但如果需要,可以使用数组( varargs )或其他类型的集合。如果客户端向我发送的内容多于预期的对象,则会抛出 IllegalArgumentException

此外,如果您不想抛出异常,您可以继续并迭代列表以绑定参数,但使用列表大小或MAX_SIZE作为限制。例如:

public void myMethod2(List<Object> limitedList) {
        final int MAX_SIZE = 2;

        int size = MAX_SIZE;
        if (limitedList.size() < MAX_SIZE) {
            size = limitedList.size();
        }

        //Iterate through the list
        for (int i = 0; i < size; i++) {
            Object obj = limitedList.get(i);
            //Logic to bind the obj to the criteria.            
        }
    }