从地图填充Java对象的方法

时间:2015-05-11 14:05:48

标签: java xml serialization jaxb deserialization

我正在处理工作中反复出现的模式。

CTE

简单示例,对象之间没有关系。更复杂的场景,其中A类具有B类成员也会发生并使用外键解决。

从数据库返回的表 处理为public class SapExample { public static void main(String[] args) { // read SAP data.. // get table List<Map<String, Object>> objects = getTable("ET_WIDGET"); for (Map<String, Object> entry : objects) { Object value = entry.get("WDGT_ID"); String id = (value != null) ? String.valueOf(value) : ""; // or null value = entry.get("WDGT_NAME"); String name = (value != null) ? String.valueOf(value) : ""; // or null value = entry.get("WDGT_DESC"); String description = (value != null) ? String.valueOf(value) : ""; // or null // create object from data //Widget obj = new Widget(id, name, description); } } private static List<Map<String, Object>> getTable(String string) { return Collections.emptyList(); } } ,其中List<Map<String, Object>>描述给定表中的一行,该行将列名称映射到类型Map<String, Object>的值,其内部大多数类型为Object或{{ 1}}。

映射包含初始化特定类型对象所需的数据,这取决于当前表。我不能改变它。

程序员以我上面展示的方式直接或间接访问数据,并创建所需对象的实例。

我发现这是一种非常冗长和不真实的编程方式。

是否可以利用JAXB或其他技术以声明方式解决此问题(例如,通过使用XML)? 如果可以使用JAXB,我该怎么办?我想我必须覆盖一些类。

2 个答案:

答案 0 :(得分:2)

首先 - 忘掉XML,因为它与你想要做的事没什么关系。

您想要的是在Map中获取数据并将其复制到普通对象中。在Apache BeanUtils库中有一个类可以做到这一点 - org.apache.commons.beanutils.BeanMap

有一些先决条件:你的目标类必须是bean类型的对象 - 换句话说,它们必须有putlic getter和setter。

然后您可以将其中一个包装在BeanMap中,如下所示:

BeanMap beanMap = new BeanMap(myObject)

然后设置对象中的字段:

beanMap.put(fieldName, value)

因此,您可以看到可以使用输入映射中条目的列名来设置目标对象中的字段。问题是列名与字段名不完全相同,因此您必须具有某种映射功能。我建议您通过在Java中创建映射来实现这一点:

someMap.put("ET_WIDGET.WIDGET_ID", "ID")

或者您使用属性文件。

您可以使用Class.newInstance方法创建对象本身,并以与上面类似的方式将表名与表名映射。

答案 1 :(得分:1)

JAXB 似乎不适合您的情况,因为它是为了处理XML而您的问题不涉及XML。

作为替代方案,您可以使用注释和反射:

创建自己的注释:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Mapped {
    String value() default "";
    String defaultValue() default "";
}

注释您的Widget / POJO:

public class Widget {
    @Mapped(key = "WDGT_ID", defaultValue = "")
    private String id;
    @Mapped(key = "WDGT_NAME", defaultValue = "")
    private String name;
    @Mapped(key = "WDGT_DESC", defaultValue = "")
    private String description;

    [constructors...]
    [getters&setters...]
}

实施可以创建POJO的“工厂/构建器”方法:

public T getObject(Map<String, Object> source, Class<T> clazz) {
    [some java introspection code]
}

您的代码将变为:

public class SapExample
{

  public static void main(String[] args)
  {
    // read SAP data..

    // get table
    List<Map<String, Object>> objects = getTable("ET_WIDGET");

    for (Map<String, Object> entry : objects) {
        Widget obj = getObject(entry , Widget.class);
    }
  }

  private static List<Map<String, Object>> getTable(String string)
  {
    return Collections.emptyList();
  }
}

这里的难点部分是“ factory ”方法。我不会在这里提供代码,因为它需要大量的时间来生成,实现可能取决于您的上下文。但我希望你能理解这个想法。