Я реализую JPA-подобный процесс: все классы, представляющие таблицу, должны быть подклассом DBTable
абстрактного класса, который содержит HashMap, связывающий имена столбцов (String) с java.lang.reflect.Field
Я получил от вызова getClass().getDeclaredFields()
в суперконструктор класса, вызываемый из конструктора подкласса.Это работает (я получаю членов, которых я хочу из подкласса).
Я хочу динамически установить эти члены подкласса из ResultSet
, который вызовет Field.set(this, ResultSet.getXXX(column))
в методе, первоначально реализованномв суперклассе в качестве помощника, но я получаю java.lang.IllegalAccessException: Class DBTable can not access a member of class MyTable with modifiers "protected"
.
Так получается, что метод выполняется в контексте суперкласса (абстрактный класс!): если я копирую / вставляюметод в моем подклассе работает нормально.
Вот фрагмент:
public abstract class DBTable {
public DBTable() {
hm = new HashMap<String,Field>();
for (Field f : getClass().getDeclaredFields()) {
hm.put(f.getAnnotation(Annot.class).value(), f); // 'annot' gives the column name
}
}
protected boolean setFieldClass(Field f, ResultSet rs, int iCol) {
Class<?> type = f.getType();
if (type == String.class) {
f.set(this, rs.getString(iCol)); // IllegalAccessException
}
}
public boolean read(ResultSet rs) {
ResultSetMetaData meta = rs.getMetaData();
for (int i = 1; i < meta.getColumnCount(); i++) {
Field f = hm.get(meta.getColumnName(i));
setFieldClass(f, rs, i); // IllegalAccessException
}
}
public abstract someAbstractOtherMethod();
}
public class MyTable extends DBTable {
@Annot("DataCol") // Set the column name to "DataCol"
protected String dataStr;
public MyTable() {
super();
}
// 'dataStr' getter/setter
// 'someAbstractOtherMethod' implementation
}
public static void main(String[] args) {
MyTable mt = new MyTable();
ResultSet rs = ...; // Execute SELECT query returning a single row with a "DataCol" column containing a varchar(32)
mt.read(rs); // IllegalAccessException
}
Метод read
, вызываемый для объекта MyTable
, унаследован от класса DBTable
который, в свою очередь, вызывает метод setFieldClass
, который выдает ошибку.Если я скопирую / вставлю метод setFieldClass
из DBTable
в MyTable
, он будет работать, как и изменение элемента dataStr
на public.
Я мог бы вызвать установщик вместо прямой установки элементазначение, но хотел бы избежать этого (я не уверен, что подклассы будут реализовывать это, и при этом они не будут давать одинаковые имена).
Спасибо, что поделились со мной своими идеями!:)