How to create bean/s(retaining column datatype in bean) dynamically after reading columns from table/s in java ?
-
You don't have access to the database schema? I'm thinking of why would you need to create beans dynamically in the first placeSujay– Sujay2013-10-03 08:14:22 +00:00Commented Oct 3, 2013 at 8:14
-
@Sujay Suppose you have an SQL editor which accepts any sql then runs. How would you represent data? You would need a dynamic bean to bind to grid.ramazan polat– ramazan polat2017-08-21 20:45:19 +00:00Commented Aug 21, 2017 at 20:45
4 Answers
UPDATE Previous answer was an attempt to solve the issue immediately. So it's not the final code for FlexBean. For the final code, visit https://github.com/ramazanpolat/flexbean
OLD ANSWER
I had the same problem so I wrote 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();
}
}
Usage:
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");
Comments
You can create classes dynamically with some framework like http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/. Alternatively you could store data in a Map where key is column name and value is column value, multiple rows could be stored in a List of Maps
Comments
You might consider Apache BeanUtils.
It provides several classes for creating beans dynamically. They all implement the DynaBean interface. For example, with the LazyDynaBean:
DynaBean myBean = new LazyDynaBean();
myBean.set("myProperty", "myValue");
Comments
There're several frameworks/libraries that are available which can help you generate classes. Evgeniy suggested javassist. There're similar libraries like cglib, asm as well that you can explore.
But I would really like to know more about your use-case because in my opinion, dynamically generated classes have their drawbacks in a statically-typed language, such as Java. Also, getting field data types, would require introspection using Java reflection mechanism. That in itself adds to complexity.
I would suggest, either of the following:
If you've access to the database schema, consider generating the bean classes beforehand. There're several tools/plugins available for your favorite IDE to achieve this.
Consider storing your data in an implementation of the Map interface. For example, you can use one of these to map your column id to the data type and another to map the column id with the data retrieved. You can then use these two maps in your code without the need of creating any beans at runtime.