2016-11-16 2 views
2

Kann ich Generika und JPA zusammen verwenden?Verwenden von Generics und jpa EntityManager-Methoden

Ich versuche, Objekte von vier Klassen in meiner Datenbank zu halten. Hier ist meine PersistService-Klasse:

Aber dann bekomme ich ein Problem mit dem Entfernen des Objekts. Ich habe die folgende Methode in der Klasse PersistService zusätzlich zu dem oben:

// Remove an object from the Database if they exist 
public static <T> void remove(Long id) { 
    EntityManager em = getEntityManager(); 
    EntityTransaction et = em.getTransaction(); 
    <T> obj = em.find(<T>.class, id); 
} 

Die letzte Zeile mir eine Kompilierung Fehler gibt. Ich habe <T>.classTClass<T> und T.class auch versucht, aber es gibt mir noch einen Kompilierzeitfehler. Wenn Sie etwas über Type Erasure erfahren, liegt das daran? Wie behebe ich dieses Problem?

+0

sollten Sie versuchen, eine GenericDao zu machen und die Kind-Klassen machen verlängern – BrunoDM

+0

Sie wollen nie in Ihrem 'PersistService' Methoden verwalteten Transaktionen haben ist. Sie möchten Transaktionsgrenzen basierend auf den logischen Abschnitten der Geschäftslogik verwalten.In der Regel werden Sie mehrere bis viele Datenbankoperationen ausführen, die entweder alle erfolgreich sein sollen oder alle fehlschlagen sollen - andernfalls bleibt Ihr System in einem inkonsistenten Zustand, in dem schwer zu programmieren ist und von dem sich schwer wiederherstellen lässt. – Rob

+0

Sie können den Klassentyp während der Kompilierzeit nicht abrufen. Sie werden genug Zeit und Ressourcen darauf verwenden, um danach zu suchen. –

Antwort

2

Sie haben begonnen, ein gutes Muster zu verwenden. Im nächsten Schritt erstellen Sie eine Unterklasse von PersistService für jeden Ihrer Entitätstypen. Ich werde auch erwähnen, dass Sie auf lange Sicht wahrscheinlich eine gemeinsame Basisklasse oder Schnittstelle für jede Ihrer Entitäten haben möchten. Zum Beispiel werde ich es Entity nennen. Diese Basisklasse (wenn es sich um eine Klasse und nicht um eine Schnittstelle handelt) kann abstrakt sein und allgemeine Methoden für alle Entitäten definieren.

public interface Entity { 
    long getId(); 
} 

können Sie die Methoden von Entity in Ihrer Implementierung von PersistService definiert verwenden (die Sie praktisch finden können, wie Sie allgemeinere einheitsbezogene Business-Logik in diesem Basisdienst oder an anderer Stelle in Ihrem Code hinzufügen).

Ihr Unternehmen A sieht aus wie

public class A extends Entity { 
} 

Ihre PersistService wird

public abstract class PersistService<T extends Entity> { 
    // Your common methods (persist, remove, etc.). 
    public abstract Class<T> getEntityClass(); 
} 

Ihre unternehmensspezifische Dienste dieses aussehen wie

public class APersistService extends PersistService<A> { 
    public Class<A> getEntityClass() { 
     return A.class; 
    } 
} 

Sie dann die getEntityClass() Methode verwenden, wenn Sie implementieren PersistService.remove().

Während die entitätsspezifischen Unterklassen das Problem lösen, das spezifische Klassenobjekt angesichts der Typlöschung zu erhalten, werden Sie feststellen, dass Sie letztendlich auch wollen, dass die Unterklasse auch entitätsspezifische Abfragen unterstützt.

0

Ich habe vielleicht die Antwort, die Sie suchen, gut, generischen Typ während der Kompilierzeit zu haben ist nicht so einfach. Da Java es dir nicht erlaubt, das direkt zu tun.

Ich habe einen Hack selbst, können Sie so etwas versuchen?

Achten Sie darauf, Ihre Ausnahmen zu behandeln.

static <T> Class getGenericType(T t){ 
    return getType(t); 
} 
static Class<?> getType(Object o){ 
    return o.getClass(); 
}