2011-01-13 17 views
6

Tengo una tabla donde el objeto principal tiene una relación opcional de varios a uno. El problema es que la tabla está configurada para establecer por defecto la columna fkey en 0.Hibernar clave externa de muchos a uno Valor predeterminado 0

Al seleccionar, usando fetch = "join", etc-- el valor predeterminado de 0 en la tecla se usa para intentar una y otra vez para seleccionar de otra tabla para el ID 0. Por supuesto, esto no existe, pero ¿cómo puedo decirle a Hibernate que trate el valor de 0 para que sea lo mismo que NULL-- para que no pase más de 20 veces buscando una relación que no funciona? t existir?

<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

¿Por qué el valor predeterminado es 0 y no NULO? Además, un FK debe ser NULL o un ID válido en la tabla de destino. ¿Tiene esa columna de hecho un límite de FK? – sblundy

Respuesta

2

Pude solucionar esto creando un tipo id-long que amplía el tipo largo integrado, pero si el ID devuelto por SQL era 0, en su lugar, devuelve null. Esto mantuvo la tolerancia de los valores predeterminados en nuestro DB mientras que Hibernate dejaba de hacer recuperaciones flojas.

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); 
    } 
} 

}

La razón de hacer cumplir defecto, ya que 0 es que Oracle trata los valores nulos de indexación y curiosamente, lo que sugiere un mejor rendimiento de las consultas con los valores explícitos vs. 'donde col es nulo [no]'

0

creo que está utilizando el tipo primitivo como sus primarias/columnas de clave externa en su objeto. En caso afirmativo, intente utilizar clases contenedoras. Porque los tipos primitivos no pueden tener valores predeterminados como nulos.

3

Hay dos formas de hacerlo, la forma en que puede ser feo en cuanto a rendimiento y la forma en que es doloroso e incómodo.

La forma potencialmente fea se hace en el extremo ToOne. El uso de anotaciones de Hibernate sería:

@Entity 
public class Foo 
{ 
    ... 

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

    ... 
} 

Desafortunadamente, esto obliga a un golpe preventivo base de datos (sin carga lenta), ya que el dispositivo puede ser nulo, y si Hibernate creado un dispositivo perezoso continuación "dispositivo == null" nunca sería cierto.

La otra forma consiste en crear un UserType personalizado que intercepte solicitudes para el ID 0 y devuelva nulo para ellos, y luego asignarlo a la clave principal del Dispositivo con @Type. Esto fuerza la interpretación 0 ~ null en todos los que tienen una clave foránea en el Dispositivo.

Cuestiones relacionadas