Java:访问字段而不知道其名称。 (“保存参考”)

时间:2013-01-21 09:15:46

标签: java orm field

我需要在不知道名字的情况下获得Field(或字段列表)。

I.e:对于自定义实体管理员,我希望能够像这样进行方法调用:

cem.getEntities(MyEntity.class, ParamMap)其中ParamMap应为Map<Field, Object>类型。

目前可以做的事情是这样的:

Map<Field, Object> params = new HashMap<Field, Object>();
params.put(MyEntity.class.getDeclaredField("someFieldName"), 20);
List<MyEntity> entitysWithSomeFieldNameEquals20 = cem.getEntities(MyEntity.class, params);

我试图避免使用查询,因为它应该首先工作“通用”,但也独立于字符串。 (它们容易出错)。因此,实体管理器使用反射来确定他需要使用的表名和列名。

但是,我仍然需要使用

MyEntity.class.getDeclaredField("someFieldName")

这将简单地将容易出错的字符串“移出”实体管理器......

我想要达到的目标是:

MyEntity.class.getDeclaredField(MyEntity.class.fields.someFieldName.toString())

因此,无论实际字段的名称是什么,都可以以保存方式引用,重构也将重构所有字段访问调用。

我不确定这是否可行。我可以为所有实体使用(封装的)枚举,但我希望,这是实现这一目标的更通用的方法。


编辑:

一个好的解决方案似乎是使用常量:

public class MyEntity{
    private static string SOME_FIELD = "some_field_name_in_database";

    @Column(name = SOME_FIELD);
    private String someField;

}

...
Map<String, Object> params = new HashMap<String, Object>();
params.put(MyEntity.SOME_FIELD, matchValue);
List<MyEntity> result = eem.getEntities(MyEntity.class, params);

这至少可以将字符串的使用减少到一个位置,可以在不影响任何其他文件的情况下维护和更改字符串。但我仍然在寻找没有常数的解决方案,因此不需要与可用字段同步: - )

1 个答案:

答案 0 :(得分:0)

好的,这只是一个想法,不容易实现,但它可以工作。

假设MyEntity看起来像这样:

public class MyEntity {
  private String foo;
  private String bar;

  public String getFoo() { return this.foo; }
  public void setFoo(String foo) { this.foo = foo; }

  public String getBar() { return this.bar; }
  public void setBar(String bar) { this.bar = bar; }

}

并且有一个界面:

public interface Pattern {
  public Class<?> getEntityClass();
  public Map<Field, Object> getFields();
}

并且有一个方法,它接受一个类并生成一个模式对象,它是给定类的一个实例:

public class PatternFactory {
  public <T> T createPattern(Class<T> klass) {
    // magic happens here
  }
}

对发出的实例的要求是它应该实现Pattern接口,这样方法getFields只返回显式设置的字段。 GetEntityClass应该返回实体类。然后可以像这样实现自定义实体管理器:

public class EntityManager {
  public <T> Collection<T> getEntities(T pattern) {
    if (!(pattern instanceof Pattern))
      throw new IllegalArgumentException();

    Class<?> klass = ((Pattern) pattern).getEntityClass();
    Map<Field, Object> fields = ((Pattern) pattern).getFields();
    // fetch objects here
  }
}

然后你可以像这样使用它:

PatternFactory pf = // obtain somehow
EntityManager em = // obtain somehow
MyEntity pattern = pf.createPattern(MyEntity.class);
pattern.setFoo("XYZ");
pattern.setBar(null);
Collection<MyEntity> result = em.getEntities(pattern);

在这种情况下,pattern.getFields将返回一个包含两个条目的地图。

当然,这里的难点在于createPattern方法的实现,在该方法中,您必须在运行时发出字节码。但是,这是可能的,可以做到。