2010-05-20 4 views
5

Also hier ist mein Rätsel. Ich programmiere ein Tool, das an alten Versionen unserer Anwendung arbeiten soll. Ich habe den Code für die Anwendung, kann aber keine der Klassen ändern. Um Informationen aus unserer Datenbank zu ziehen, habe ich ein DTO, das von Hibernate aufgefüllt wird. Es verbraucht ein Datenobjekt für die Version 1.0 unserer App, mit dem schlauen Namen DataObject. Unten ist die DTO-Klasse.Muster für versionsspezifische Implementierungen einer Java-Klasse

public class MyDTO { 
    private MyWrapperClass wrapper; 

    public MyDTO(DataObject data) { 
     wrapper = new MyWrapperClass(data); 
    } 
} 

Der DTO wird durch eine Hibernate-Abfrage instanziiert wie folgt:

select new com.foo.bar.MyDTO(t1.data) from mytable t1 

Nun, ein wenig Logik auf dem Datenobjekt benötigt wird, so dass ich für sie eine Wrapper-Klasse. Beachten Sie, dass das DTO eine Instanz der Wrapperklasse und nicht das ursprüngliche Datenobjekt speichert.

public class MyWrapperClass { 

    private DataObject data; 

    public MyWrapperClass(DataObject data) { 
     this.data = data; 
    } 

    public String doSomethingImportant() { ... version-specific logic ... } 
} 

Das funktioniert gut, bis ich an der Version 2.0 unserer Anwendung arbeiten muss. Nun sind DataObject in den beiden Versionen sehr ähnlich, aber nicht gleich. Dies führte zu verschiedenen Unterklassen von MyWrapperClass, die ihre eigene versionsspezifische doSomethingImportant() implementieren. Geht immer noch gut. Aber wie instanziert myDTO die passende versionsspezifische MyWrapperClass? Hibernate wiederum instantiiert MyDTO, also ist es nicht so, dass ich im Frühling eine Abhängigkeit herstellen kann.

Ich würde gerne MyDTO (und meine Dutzende von anderen DTOs) für beide Versionen des Tools wiederverwenden, ohne die Klasse duplizieren zu müssen. Wiederhole dich nicht und all das. Ich bin mir sicher, dass es ein sehr einfaches Muster gibt, das mir fehlt, das mir helfen würde. Irgendwelche Vorschläge?

Antwort

0

Mein Kollege und ich versuchten viele Optionen. Wir entschieden uns für Hibernate's schlecht dokumentierte ResultTransformer-Schnittstelle (wirklich, Hibernate, der Mangel an Dokumentation dort ist beschämend). Obwohl die Verwendung des Transformers uns zwang, ein Array Object [] in unserem MyDTO-Konstruktor manuell zu analysieren, war es ein würdiger Kompromiss.

Im ResultTransformer haben wir eine versionsspezifische WrapperFactory über Spring eingefügt. Wir haben unsere Abfragen geändert, damit ResultTransformer MyDTO instanziieren kann, und voila! Problem gelöst. Im Folgenden finden Sie unsere geänderte Abfrage und DTO-Klasse:

"select t1.data from mytable t1" 

public class MyDTO<T> { 
    private MyWrapperClass wrapper; 

    public MyDTO(Object[] fields, WrapperFactory<T> wrapperFactory) { 
     T data = (T) fields[0];   
     wrapper = wrapperFactory.newWrapper(data); 
    } 
} 

Wie pro meine Kommentare zu Guillaume hat der Interceptor nicht wie erhofft funktionieren. Vermutlich, weil MyDTO keine persistente Klasse ist.

Wir haben auch versucht, den DTO Zugriff auf den ApplicationContext direkt über eine Singleton-Klasse und von dort erhalten die WrapperFactory. Obwohl dies funktionierte, war es vorhersehbar unsere Unit Tests, und wir verwarfen den Ansatz.

1

Sie können einen Hibernate Interceptor verwenden und die instantiate(String entityName, EntityMode entityMode, Serializable id) implementieren.

In dieser Methode können Sie eine MyWrapperClass an Ihr Datenobjekt übergeben. Abhängig von der Version Ihrer App wird der Wrapper anders aussehen. Der Interceptor kann auf Sitzungsebene oder auf Sitzungs-Factory-Ebene festgelegt werden.

+0

Dies hat für uns nicht funktioniert, vermutlich weil MyDTO keine persistente Klasse ist. Die einzigen Interceptor-Methoden, die ausgelöst wurden, waren afterTransactionBegin(), onPrepareStatement(), beforeTransactionCompletion() und afterTransactionCompletion(). Keiner von denen gab uns das richtige Fenster, um die Daten zu manipulieren. Sie haben uns jedoch auf den richtigen Pfad gesetzt, als wir schließlich Hibernate's ResultTransformer-Schnittstelle gefunden haben. Vielen Dank! –

+0

Cool, froh, ich könnte ein wenig helfen :) – Guillaume

Verwandte Themen