Hibernate多对一外键默认值0

use*_*648 6 java orm hibernate many-to-one

我有一个表,其中父对象具有可选的多对一关系.问题是该表被设置为将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"/>
Run Code Online (Sandbox Code Playgroud)

Ale*_*sky 6

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

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

@Entity
public class Foo
{
    ...

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

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

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


use*_*648 3

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

}

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