2010-06-09 12 views
20

Wir haben die folgenden KlassenWie die DiscriminatorValue zur Laufzeit bekommen

@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 { 
} 

Und das

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

Jetzt muss ich zur Laufzeit wissen, ob die ApplicationProcess von DiscriminatorValueAP or APS ist. Da dies automatisch von jpa gehandhabt wird, habe ich keine Möglichkeit, diesen Wert zu erhalten.

Wir rufen eine Methode auf, die einen ApplicationProcess als Parameter verwendet, und ich möchte vermeiden, mit instanceof zu überprüfen, welcher Typ es ist. Wäre kühler sein, wenn ich so etwas tun konnte

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

Antwort

34

Sie können Ihre Scheider als schreibgeschützte Eigenschaft Karte:

public class ApplicationProcess { 

    ... 

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

} 
+0

@Shervin: Sie können, aber es ist keine gute Idee, Ihre Logik sollte sich nicht darauf verlassen . –

+1

@Pascal: Ich denke ich muss. Auf der xhtml-Seite habe ich keine Möglichkeit im EL-Ausdruck 'instanceof' zu sagen (glaube ich). Also könnte ich das brauchen. –

+1

@Shervin: Es tut mir leid, dies zu sagen, aber es scheint, dass Sie einen großen Fehler in Ihrem Design haben, die ** Ansicht ** sollte sich NIEMALS auf einen Diskriminatorwert verlassen müssen (dies gilt für Business-Code aber noch mehr für die Aussicht). –

5

wir eine Methode aufrufen, die einen Applicationprocess als Parameter übernimmt, und ich möchte mit vermeiden Instanceof zu prüfen, welche Art es ist. Wäre kühler sein, wenn ich etwas tun könnte, wie (...)

Ich glaube nicht, es kühler sein würde, scheint dies schlimmer als instanceOf ich rufe: Wenn Sie aus irgendeinem Grunde den Unterscheidungswert zu ändern, es würde deinen Code brechen.

Wenn Sie den Typ überprüfen müssen, verwenden Sie instanceOf. Ein Trick mit dem Diskriminator wird die Dinge nicht schöner machen, es würde Ihren Code weniger robust machen.

+1

+1 stimme ich voll und ganz zu. Vielleicht ist dieses Refactoring meine anwendbar: http://www.c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism –

+0

Aber dann müsste ich etwas tun: Pseudo-Code: 'if (nicht applicationProcess instanceof ApplicationProcessScheme)', weil Ich kann nicht gegen ApplicationProcess überprüfen, da ApplicationProcessScheme auch das Also würde der Code sein "ob (obj instanceof ApplicationProcessScheme) {// weil es keine! Instanceof} else {// Wir haben ein Kind!}' –

+1

@ Shervin: Ja, das müsstest du tun. Ich sage nicht, dass es ideal ist, ich würde sagen, dass es sich schlechter läge, sich auf Metadaten zu verlassen. Eigentlich würde ich @ Ashs Vorschlag ausgraben. –

29

Ich kann einige Fälle vorstellen, in denen es hilfreich sein könnte, aber trotz der Grund, warum Sie diese benötigen, könnten Sie auf Ihre abstrakten Klasse erstellen methode wie

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

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

Ein Anwendungsfall könnte sein: einige systemweite Übersetzungstabelle mit Typen (Land, Sprache, Geschlecht, ...) und pro Typ mehrere Schlüssel ("pl", "uk", "us", ...) und Werte ("Polen", "Vereinigtes Königreich", ...). Einige der Typen können in '@ OneToMany'-Beziehungen verwendet werden, wie z. B. ein Land in einer' @Entity-Adresse', aber andere Typen können nur durch Abfragen der Datenbank verwendet werden. Also: Die Basisklasse würde die meisten Typen behandeln, aber einige spezifische würden ihre eigene abgeleitete Klasse haben. – Arjan

+0

für mich war das Problem mit der angenommenen Antwort, wenn der beanstandete gerade erstellt und noch nicht gespeichert, Diskriminator ist nicht vorhanden. In Testfällen, in denen Daten tatsächlich nicht in db gespeichert werden, gab es Probleme damit. Das hat super funktioniert. Danke –

+0

Das funktioniert super. –

0

Sie können Formula Annotation verwenden. Wenn Sie Hibernate verwenden, können Sie den Code verwenden unten nach this link:

private String theApType; 

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

Natürlich wäre in der Lage Sie es in Ihren Abfragen zu verwenden.