Reputation: 3866
I am trying to build a User
class from SQL query ResultSet
.
I am using my user class to get field names and use them as column names while building my SELECT
query.
In this case my query has id
and email
in it's selections.
Query: "SELECT " + String.join(", ", columns) + " FROM " + table + ";"
public class User {
private int id;
private String email;
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
I have the problem in my parser class where I parse the results from database to an ArrayList<User>
. Meanwhile I need to get the column types and field types dynamically.
Here is the loop of rows retrieved from the database:
while (resultSet.next()) {
// columnCount is equal to the classes field count
// since ResultSet starts indexes from 1, I added 1 to columnCount
for (int i = 1; i < columnsCount + 1; i++) {
// get the class of the wanted results
// Ex: User
Class<? extends Object> object = instance.getClass();
// column name from index
// Ex: id
String columnName = metaData.getColumnName(i);
// setter method name in the class
// Ex: setId
String setterName = "set" + Utils.firstLetterToUpperCase(columnName);
Method method = null;
Class<?> type = null;
try {
// array of declared fields of the class
// Ex: [id, email]
Field[] fields = object.getDeclaredFields();
// type of that field
// since ResultSet starts indexes from 1, I subtracted 1 from `i`
// Ex: int
type = fields[i - 1].getType();
// Ex:
// Method is equal to the `setId(int id)`
// setterName = setId, type = int
method = object.getDeclaredMethod(setterName, type);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// getter method to invoke on resultSet object to get the type dynamically
// Ex: getterName = getId
String getterName = "get" + Utils.firstLetterToUpperCase(type.getName());
try {
Method resultSetGetterMethod = null;
try {
// Ex:
// public int com.mysql.jdbc.ResultSetImpl.getInt(int) throws java.sql.SQLException
// easier: getInt(int x)
// getterName = getInt, type = int
resultSetGetterMethod = resultSet.getClass().getMethod(getterName, type);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// this part gives the error
// "object is not an instance of declaring class"
// --------------------------------------------------------- //
// Exception: "object is not an instance of declaring class" //
// --------------------------------------------------------- //
method.invoke(object,
// it should call `getInt(int x)` method
// on `resultSet` with `i` as the argument, which
// is the index of the int column in the `resultSet`
resultSetGetterMethod.invoke(resultSet, i) // This line
);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
results.add(object);
}
}
I tried to explain what I tried to do in the comments, if it's not clear enough I can update the question.
I marked the code that throws the excetion with:
// --------------------------------------------------------- //
// Exception: "object is not an instance of declaring class" //
// --------------------------------------------------------- //
Why am I getting this error?
Upvotes: 0
Views: 1092
Reputation: 8387
You invok the method with the class, but you need an instance of it, try this:
method.invoke(instance,resultSetGetterMethod.invoke(instance,resultSet, i));
Upvotes: 2