【问题标题】:Hibernate Many-To-One Foreign Key Default 0Hibernate 多对一外键默认 0
【发布时间】:2011-06-08 06:37:17
【问题描述】:

我有一个表,其中父对象具有可选的多对一关系。问题是该表设置为将 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"/>

【问题讨论】:

  • 为什么默认值是0而不是NULL?此外,FK 必须为 NULL 或目标表中的有效 ID。该列实际上是否有 FK 常量?

标签: java hibernate orm many-to-one


【解决方案1】:

我可以通过创建一个扩展内置 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”相比具有更好的查询性能

【讨论】:

    【解决方案2】:

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

    潜在的丑陋方式是在 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 解释。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2013-05-10
        • 2018-03-29
        • 2012-03-22
        • 2014-12-23
        • 1970-01-01
        • 1970-01-01
        • 2016-09-18
        • 2011-12-15
        • 1970-01-01
        相关资源
        最近更新 更多