7

我有一个表,其中父对象具有可选的多对一关系。问题是该表设置为将 fkey 列默认为 0。

选择时,使用 fetch="join" 等 - fkey 上的默认值 0 被用于反复尝试从另一个表中选择 ID 0。当然这不存在,但我怎么能告诉 Hibernate 将值 0 视为与 NULL 相同 - 在获取不存在的关系时不要循环 20 多次?

<many-to-one name="device" lazy="false" class="Device" not-null="true" access="field" cascade="none" not-found="ignore">
<column name="DEVICEID" default="0" not-null="false"/>

4

3 回答 3

6

有两种方法可以做到这一点,一种会在性能方面变得丑陋,另一种是痛苦和尴尬。

潜在的丑陋方式是在 ToOne 端完成的。使用 Hibernate Annotations 将是:

@Entity
public class Foo
{
    ...

    @ManyToOne
    @JoinColumn( name = "DEVICEID" )
    @NotFound( action = NotFoundAction.IGNORE )
    private Device device;

    ...
}

不幸的是,这会强制执行抢占式数据库命中(无延迟加载),因为 device 可以为 null,如果 Hibernate 创建了一个延迟 Device,则“device == null”永远不会为真。

另一种方法是创建一个自定义 UserType,它拦截对 ID 0 的请求并为它们返回 null,然后使用 @Type将其分配给Device的主键。这会强制每个具有 Device 外键的 0 ~ null 解释。

于 2011-01-14T21:07:40.753 回答
3

我可以通过创建一个扩展内置 Long 类型的 id-long 类型来解决此问题,但如果从 SQL 返回的 id 为 0,则改为返回 null。这在我们的数据库中保留了默认 0 的允许值,同时让休眠状态停止执行延迟提取。

public class IdentifierLongType extends LongType implements IdentifierType {

@Override
public Object get(ResultSet rs, String name) throws SQLException {
    long i = rs.getLong(name);
    if (i == 0) {
        return null;
    } else {
        return Long.valueOf(i);
    }
}

}

强制执行显式默认值 0 的原因是 Oracle 奇怪地处理索引和空值,这表明使用显式值与 'where col is [not] null' 相比具有更好的查询性能

于 2011-01-26T05:53:03.023 回答
0

我认为您使用原始类型作为对象中的主键/外键列。如果是,那么尝试使用包装类。因为原始类型不能将默认值设为 null。

于 2011-01-13T04:24:07.557 回答