代码之家  ›  专栏  ›  技术社区  ›  Mike Monkiewicz

Java类的特定版本实现模式

  •  5
  • Mike Monkiewicz  · 技术社区  · 14 年前

    所以这是我的难题。我正在编程一个需要在我们的应用程序的旧版本上工作的工具。我有应用程序的代码,但不能更改任何类。为了从数据库中提取信息,我有一个由Hibernate填充的DTO。它使用了我们应用程序1.0版的数据对象,名为data object。下面是DTO类。

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

    DTO通过Hibernate查询实例化,如下所示:

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

    现在,在数据对象之上需要一些逻辑,所以我为它创建了一个包装类。注意,DTO存储包装类的一个实例,而不是原始数据对象。

    public class MyWrapperClass {
    
        private DataObject data;
    
        public MyWrapperClass(DataObject data) {
            this.data = data;
        }
    
        public String doSomethingImportant() { ... version-specific logic ... }
    }
    

    在我需要处理我们应用程序的2.0版本之前,这是很好的工作。现在,两个版本中的DataObject非常相似,但不相同。这导致了MyWrapperClass的不同子类,这些子类实现了它们自己的版本特定的doSomementImportant()。还可以。但是,mydto如何实例化适当的特定于版本的mywrapperClass?Hibernate轮流实例化mydto,所以我不能在春季@autowire一个依赖项。

    我希望在不需要复制类的情况下,将mydto(和我的数十个其他dto)重新用于工具的两个版本。不要重复你自己的话。我相信我遗漏了一个非常简单的模式,这将有助于解决这个问题。有什么建议吗?

    2 回复  |  直到 14 年前
        1
  •  1
  •   Guillaume    14 年前

    你可以用冬眠 Interceptor 一个工具 instantiate(String entityName, EntityMode entityMode, Serializable id) .

    在该方法中,可以将MyWrapperClass传递给数据对象。根据应用程序的版本,包装器将有所不同。拦截器可以在会话级别或会话工厂级别设置。

        2
  •  0
  •   Mike Monkiewicz    14 年前

    我和我的同事尝试了很多选择。我们决定使用Hibernate记录不良的ResultTransformer接口(实际上,Hibernate缺少文档是可耻的)。虽然使用Transformer迫使我们手动解析mydto构造函数中的对象[]数组,但这是一个值得权衡的问题。

    在ResultTransformer中,我们通过Spring注入了一个特定于版本的包装器工厂。我们更改了查询以允许resultTransformer实例化mydto,瞧!问题解决了。下面是我们修改过的查询和DTO类:

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

    根据我对桂林的评论,拦截器没有按预期工作。大概是因为mydto不是持久类。

    我们还尝试让DTO通过一个singleton类直接访问applicationContext,并从中获得wrapperFactory。尽管这样做有效,但可以预见的是,fubar完成了我们的单元测试,我们放弃了这种方法。