How to create bean/s(retaining column datatype in bean) dynamically after reading columns from table/s in java ?
4 回答
更新 先前的答案是试图立即解决问题。所以这不是 FlexBean 的最终代码。最终代码请访问https://github.com/ramazanpolat/flexbean
旧答案
我有同样的问题,所以我写了 FlexBean。
public class FlexBean {
private List<String> propertyNames = new ArrayList<>();
private Map<String, Object> propertyValueMap = new LinkedHashMap<>();
private List<Type> propertyTypes = new ArrayList<>();
public FlexBean() {
}
public void setProperties(Map<String, Object> props){
for (String propName:props.keySet()){
addProperty(propName, props.get(propName));
}
}
public void addPropertyNames(List<String> propertyNames){
for (String name: propertyNames) {
addProperty(name);
}
}
public Collection<Object> getPropertyValues(){
return propertyValueMap.values();
}
public List<String> getPropertyNames() {
return propertyNames;
}
public Map<String, Object> getPropertyValueMap() {
return propertyValueMap;
}
public List<Type> getPropertyTypes() {
return propertyTypes;
}
public void addProperty(String propName, Type propType){
propertyNames.add(propName);
propertyTypes.add(propType);
}
public void addProperty(String propName){
// default property type is String
addProperty(propName, String.class);
}
public void addProperty(String propName, Object value){
addProperty(propName);
setProperty(propName, value);
}
public void addProperty(String propName, Type propType, Object value){
addProperty(propName, propType);
setProperty(propName, value);
}
public int getPropertyIndex(String propName){
return propertyNames.indexOf(propName);
}
public Type getPropertyType(String propName){
int index = getPropertyIndex(propName);
return Iterables.get(propertyTypes,index);
}
public void setProperty(String propName, Object propValue){
propertyValueMap.put(propName, propValue);
}
public Object getPropertyValue(String propName){
return propertyValueMap.get(propName);
}
public <Any> Any getTypedPropertyValue(String propName){
return (Any)((Any) propertyValueMap.get(propName));
}
public Object getProperty(int propIndex){
return Iterables.get(propertyValueMap.entrySet(),propIndex).getValue();
}
}
用法:
FlexBean flexBean = new FlexBean();
flexBean.addProperty("prop1", 1); // int inferred
flexBean.addProperty("prop2", "value2"); // string inferred
flexBean.addProperty("prop3", 0.1f); // float inferred
for (Object o: flexBean.getPropertyValues()) {
System.out.println(o);
}
int prop1 = flexBean.getTypedPropertyValue("prop1");
String prop2 = flexBean.getTypedPropertyValue("prop2");
float prop3 = flexBean.getTypedPropertyValue("prop3");
您可以使用http://www.csg.ci.iu-tokyo.ac.jp/~chiba/javassist/等框架动态创建类。或者,您可以将数据存储在 Map 中,其中键是列名,值是列值,多行可以存储在 Map 列表中
您可能会考虑使用 Apache BeanUtils。
它提供了几个用于动态创建 bean 的类。它们都实现了DynaBean接口。例如,使用LazyDynaBean
:
DynaBean myBean = new LazyDynaBean();
myBean.set("myProperty", "myValue");
有几个可用的框架/库可以帮助您生成类。Evgeniy 建议使用 javassist。有类似的库,如 cglib、asm 以及您可以探索。
但我真的很想更多地了解您的用例,因为在我看来,动态生成的类在静态类型语言(如 Java)中存在缺陷。此外,获取字段数据类型需要使用 Java 反射机制进行自省。这本身就增加了复杂性。
我会建议,以下任一:
如果您可以访问数据库模式,请考虑预先生成 bean 类。您最喜欢的 IDE 可以使用多种工具/插件来实现此目的。
考虑将数据存储在 Map 接口的实现中。例如,您可以使用其中一个将列 ID 映射到数据类型,另一个将列 ID 与检索到的数据映射。然后,您可以在代码中使用这两个映射,而无需在运行时创建任何 bean。