2011-01-13 82 views
6

我有一个表,父对象有一个可选的多对一关系。问题是表被设置为默认fkey列为0.休眠多对一外键默认0

当选择时,使用fetch =“join”等等,fkey上的默认值0被用于反复尝试以反复选择从另一张表中获得ID0。当然这并不存在,但我怎么能告诉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

更好的查询性能为什么默认值是0而不是NULL?另外,FK必须是NULL或目标表中的有效ID。该列实际上是否具有FK常量? – sblundy 2011-01-13 04:07:38

回答

2

我能够通过创建一个扩展内置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处理索引和空值奇怪的是,这有明确的价值观与“其中山坳为[不]空”

0

我认为你正在使用原始类型作为你的目标你的主/外键列。如果是,那么尝试使用包装类。因为基元类型不能将默认值设置为null。

3

有两种方法可以做到这一点,可以得到难看的表现方式,以及痛苦和尴尬的方式。

可能丑陋的方式在ToOne结束。使用Hibernate注解这将是:

@Entity 
public class Foo 
{ 
    ... 

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

    ... 
} 

不幸的是,这迫使抢占数据库命中(无延迟加载),因为设备可以为空,如果休眠创建一个懒惰的设备然后选择“设备== NULL”绝不会真正。

另一种方式涉及创建一个自定义的UserType,它拦截ID 0的请求并为它们返回null,然后使用@Type将其分配给Device的主键。这强制每个使用外键的每个人的0〜null解释进入Device。