2010-06-09 14 views
20

tenemos las siguientes clasesCómo conseguir el DiscriminatorValue en tiempo de ejecución

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // optional annotation as this is default 
@DiscriminatorColumn(name = "apType", discriminatorType = DiscriminatorType.STRING, length = 255) 
@DiscriminatorValue("AP") 
public class ApplicationProcess { 
} 

Y esto

@Entity 
@DiscriminatorValue("APS") 
public class ApplicationProcessScheme extends ApplicationProcess { 
} 

Ahora necesito saber en tiempo de ejecución si el ApplicationProcess es de DiscriminatorValueAP or APS. Dado que jpa lo maneja automáticamente, no tengo forma de obtener este valor.

Estamos llamando a un método que toma un ApplicationProcess como parámetro, y quiero evitar el uso de instanceof para verificar de qué tipo es. Sería más fresco si podía hacer algo como

applicationProcess.getApType().equals("AP"); 

Respuesta

34

Puede asignar el discriminador como de sólo lectura propiedad:

public class ApplicationProcess { 

    ... 

    @Column(name = "apType", insertable = false, updatable = false) 
    private String apType; 

} 
+0

@Shervin: Puedes, pero no es una buena idea, tu lógica no debería depender de eso . –

+1

@Pascal: Creo que tengo que hacerlo. En el lado xhtml no tengo forma en la expresión EL para decir 'instanceof' (creo). Entonces podría necesitar esto. –

+1

@Shervin: Lamento decirlo, pero parece que tienes un defecto importante en tu diseño, ** ver ** NUNCA tiene que depender de un valor discriminador (esto es cierto para el código comercial, pero aún más para la vista). –

5

Estamos llamando a un método que toma un ApplicationProcess como parámetro, y quiero evitar el uso de instanceof para comprobar qué tipo es. Sería más fresco si podía hacer algo así (...)

no creo que sería más fresco, esto parece peor que llamar instanceOf a mí: si por cualquier razón se cambia el valor discriminador, se rompería tu código.

Si necesita verificar el tipo, use instanceOf. Un truco usando el discriminador no va a hacer las cosas más agradables, solo haría que tu código sea menos robusto.

+1

+1 Estoy totalmente de acuerdo. Quizás esta refactorización sea aplicable: http://www.c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism –

+0

Pero entonces tendría que hacer algo como esto: pseudocódigo: 'if (no applicationProcess instanceof ApplicationProcessScheme)', porque No puedo verificar contra ApplicationProcess porque ApplicationProcessScheme también coincidiría con Así que el código sería 'if (obj instanceof ApplicationProcessScheme) {// porque no hay! Instanceof} else {// Tenemos un hijo!}' –

+1

@Shervin: Sí, tendrías que hacer eso. No digo que sea ideal, estoy diciendo que confiar en los metadatos sería peor. De hecho, me gustaría excavar la sugerencia de @ Ash. –

29

me puedo imaginar pocos casos en los que podría ser útil, pero a pesar de la razón de por qué es necesario esto, se podía crear en su clase abstracta método como

@Transient 
public String getDiscriminatorValue(){ 
    DiscriminatorValue val = this.getClass().getAnnotation(DiscriminatorValue.class); 

    return val == null ? null : val.value(); 
} 
+1

Un caso de uso podría ser: alguna tabla de traducción de todo el sistema con tipos (país, idioma, género, ...) y por tipo de claves múltiples ("pl", "uk", "nos", ...) y valores ("Polonia", "Reino Unido", ...). Algunos de los tipos se pueden usar en relaciones '@ OneToMany', como country se puede usar en una' @Entity Address', pero otros tipos solo se pueden usar consultando la base de datos. Entonces: la clase base manejaría la mayoría de los tipos, pero algunos específicos tendrían su propia clase derivada. – Arjan

+0

para mí el problema con la respuesta aceptada fue cuando el objeto objetado se acaba de crear y aún no se ha guardado, el discriminador no está presente. En los casos de prueba donde los datos realmente no persisten en db, tuve problemas con eso. Esto funcionó muy bien. Gracias –

+0

Esto está funcionando genial. –

0

Puede usar Anotación de fórmula. Si está usando Hibernate, puede utilizar el código de abajo según la this link:

private String theApType; 

@Formula("apType") 
String getTheApType() { 
    return theApType; 
} 

Por supuesto que sería capaz de utilizarlo en sus consultas.

Cuestiones relacionadas