9

I have two rows in MySQL like this

+---------+---------+
| foo     | bar     |
+---------+---------+
|         | NULL    |
|         |         |
+---------+---------+

Where empty are empty strings "".

Now I want to get both of them. I use Criteria and Restrictions.eqOrIsNull() on both columns, but it always returns only one row.

The code is like this

criteria.add(Restrictions.eqOrIsNull("foo", ""));
        .add(Restrictions.eqOrIsNull("bar", ""));

And when I add criteria only on foo, it returns two rows. But for bar, it only returns the second, which is empty.

The javadoc says, Apply an "equal" constraint to the named property. If the value is null, instead apply "is null". So am I getting this wrong, or it should be used in other ways?

UPDATE:
Sorry, I'm so careless. The doc states it clearly. This method works according to the value passed to it, not the actual value of the named property stored in DB.
Source code on Github:

public static Criterion eqOrIsNull(String propertyName, Object value) {
    return value == null
            ? isNull( propertyName )
            : eq( propertyName, value );
}

So in my case, eqOrIsNull returns eq(""). I should have used disjunction of eq and isNull, like Gregory answered.

4

3 回答 3

4

对命名属性应用“相等”约束。如果值为 null,则改为应用“is null”。

这意味着,is null仅当 NULL 作为值传递时才会应用。如果您指定任何其他字符串作为值,equal则仅适用于此。

当您不确定在运行时作为参数传递给参数值的实际值时,这很有用。在这种情况下,以传统方式,您需要根据非空条件放置非空检查和写入标准,或者您需要按照 Gregory 的回答中提到的方式编写标准。

牢记所有这些事实,您应该得到问题的答案。你只得到那些包含空值的行而不是那些具有 NULL 值的行,因为你已经指定了一个空字符串作为第二个参数。如果您将 NULL 指定为第二个参数,您将只获得那些具有 NULL 值的行。

让我知道这是否对您有帮助。

于 2013-10-12T08:44:09.777 回答
3

检查此代码是否符合您的要求 -

criteria.add(Restrictions.or(Restrictions.eq("foo", ""), Restrictions.isNull("foo")))
                .add(Restrictions.or(Restrictions.eq("bar", ""), Restrictions.isNull("bar")));

此代码段使用 Hibernate 3.5.0-CR-2 API。

于 2013-10-11T19:06:46.150 回答
0

是的,如果以前从未使用过,而且从 ORM 抽象的角度来看,这将非常模糊,完全无法区分 eq null 或 is null。那是遗留的 SQL 思维。

我首先还认为这是一条捷径,or(eq("foo"), isNull("foo")) 因为我在顶部有我自己的过滤器层,标准eq总是像eqOrIsNull.

强文本

/**
 * Checks if the given property is <code>null</code> or equals the given
 * value. If the given value is <code>null</code> it is only checked for
 * being <code>null</code>.
 *
 * @param property Property name
 * @param value Value to check against
 *
 * @return Disjunction
 */
public static Criterion isValueEqOrNull(final String property, final Object value)
{
    Objects.requireNonNull(property, "property must not be null");

    if (value == null)
        return Restrictions.isNull(property);
    else
        return Restrictions.or(Restrictions.eq(property, value), Restrictions.isNull(property));
}
于 2020-10-06T20:17:10.387 回答