2010-05-20 5 views
5

Así que aquí está mi enigma. Estoy programando una herramienta que necesita trabajar en versiones anteriores de nuestra aplicación. Tengo el código para la aplicación, pero no puedo alterar ninguna de las clases. Para extraer información de nuestra base de datos, tengo un tipo de DTO que está poblado por Hibernate. Consume un objeto de datos para la versión 1.0 de nuestra aplicación, inteligentemente llamado DataObject. Debajo está la clase DTO.Patrón para implementaciones específicas de la versión de una clase Java

public class MyDTO { 
    private MyWrapperClass wrapper; 

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

El DTO se instancia a través de una consulta de Hibernate como sigue:

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

Ahora, se necesita un poco de lógica en la parte superior del objeto de datos, así que hice una clase contenedora para ello. Tenga en cuenta que el DTO almacena una instancia de la clase contenedora, no el objeto de datos original.

public class MyWrapperClass { 

    private DataObject data; 

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

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

Esto funciona bien hasta que necesite trabajar en la versión 2.0 de nuestra aplicación. Ahora DataObject en las dos versiones es muy similar, pero no es lo mismo. Esto dio como resultado diferentes subclases de MyWrapperClass, que implementan su propio doSomethingImportant() específico de la versión. Todavía estoy bien. ¿Pero cómo myDTO instancia el MyWrapperClass apropiado específico de la versión? Hibernate a su vez crea una instancia de MyDTO, por lo que no es como si pudiera @aumentar una dependencia en Spring.

Me encantaría reutilizar MyDTO (y mis docenas de otros DTO) para las dos versiones de la herramienta, sin tener que duplicar la clase. No te repitas, y todo eso. Estoy seguro de que hay un patrón muy simple que me falta que ayudaría a esto. ¿Alguna sugerencia?

Respuesta

0

Mi compañero de trabajo y yo probamos muchas opciones. Nos decidimos por usar la interfaz ResultTransformer mal documentada de Hibernate (en realidad, Hibernate, la falta de documentación es vergonzosa). Aunque el uso del Transformer nos obligó a analizar manualmente una matriz Object [] en nuestro constructor MyDTO, fue una valiosa compensación.

En ResultTransformer, inyectamos un WrapperFactory específico de la versión a través de Spring. Cambiamos nuestras consultas para permitir que ResultTransformer instanciara MyDTO, y ¡listo! Problema resuelto. A continuación se presentan nuestra clase de consulta y DTO modificación:

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

Según mis comentarios a Guillaume, el interceptor no funcionó como se esperaba. Presumiblemente porque MyDTO no es una clase persistente.

También intentamos hacer que la DTO acceda a ApplicationContext directamente a través de una clase singleton, y de allí obtener WrapperFactory. Aunque esto funcionó, predeciblemente cubrió nuestras pruebas unitarias, y desechamos el enfoque.

1

Puede utilizar un implemento de Hibernate Interceptorinstantiate(String entityName, EntityMode entityMode, Serializable id).

En ese método, puede pasar un MyWrapperClass a su objeto de datos. Dependiendo de la versión de su aplicación, el contenedor será diferente. El interceptor se puede establecer a nivel de sesión o en el nivel de fábrica de sesión.

+0

Esto no funcionó para nosotros, presumiblemente porque MyDTO no es una clase persistente. Los únicos métodos Interceptor que se desencadenaron fueron afterTransactionBegin(), onPrepareStatement(), beforeTransactionCompletion() y afterTransactionCompletion(). Ninguno de ellos nos dio la ventana correcta para manipular los datos. Sin embargo, nos puso en el camino correcto, ya que finalmente encontramos la interfaz ResultTransformer de Hibernate. ¡Gracias! –

+0

Genial, me alegro de poder ayudar un poco :) – Guillaume

Cuestiones relacionadas