Ormlite: используйте generic как тип для id - PullRequest
0 голосов
/ 23 марта 2012

Я использую ormlite для взаимодействия с базой данных в Java. Работает нормально.

Теперь я хочу создать общий класс сущностей. Возможно, я начну с небольшого кода, чтобы объяснить это.

AbstractId - это что-то вроде базового класса для всех идентификаторов:

public abstract class AbstractId {
    public AbstractId(String id) {
        this.id = id;    
    }

    public String value() {
        return this.id;
    }
}

Расширено до:

   public class SampleId extends AbstractId {
        public SampleId(String id) {
            super(id);
        }
    }

Теперь у меня есть абстрактная базовая сущность для сохранения набора текста;)

public abstract class AbstractEntity<T> {

    @DatabaseField(id = true, columnName = "id")
    private T      id;

    @DatabaseField(columnName = "name", canBeNull = false)
    private String name;

    public AbstractEntity() {
    }
}

, который расширяется образцом сущности:

@DatabaseTable(tableName = "sample")
public class SampleEntity<T extends AbstractId> extends AbstractEntity<T> {

    @DatabaseField(canBeNull = false, columnName = "key")
    private String otherValue;

    public SampleEntity() {
    }
}

Так, как я могу сохранить Т? Экземпляр сущности создан

SampleEntity<SampleId> entity = new SampleEntity<>() // (*)

Я попытался создать новый BaseDataType и настроить DatabaseField для использования в качестве persisterClass:

public class AbstractIdPersister extends BaseDataType {

    public AbstractIdPersister(SqlType sqlType, Class<?>[] classes) {
        super(sqlType, classes);
    }

    @Override
    public Object parseDefaultString(FieldType fieldType, String defaultStr)
            throws SQLException {
        return null;
    }

    @Override
    public Object javaToSqlArg(FieldType fieldType, Object obj) {
        AbstractId abstractId = (AbstractId) obj;
        return abstractId.value();
    }

    @Override
    public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos)
            throws SQLException {            
        // HOW DO I GET THE GENERIC TYPE DEFINED ABOVE (*)     
    }

    @Override
    public Object resultToSqlArg(FieldType fieldType, DatabaseResults results,
            int columnPos) throws SQLException {
        return results.getString(columnPos);
    }

}

не сработало ... конечно ..

У кого-нибудь есть идеи, как решить эту проблему? Спасибо!

1 Ответ

1 голос
/ 02 апреля 2012

Итак, учитывая вашу иерархию, ORMLite будет иметь проблему, когда ему нужно будет создать экземпляр вашего абстрактного класса из связанного поля базы данных. Вот что пытается сделать метод sqlArgToJava. Например, в типе DATE_LONG дата хранится в базе данных как длительные миллисекунды, поэтому метод sqlArgToJava:

public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) {
    // create a Date object
    return new Date((Long) sqlArg);
}

Очевидно, что нет способа создать экземпляр AbstractId. Вместо этого вам нужно будет создать персистент для каждого из подклассов.

Если вы хорошо разбираетесь в рефлексии, то вы могли бы сделать что-то вроде следующего, но это, конечно же, хак. Я думаю, что создание персистера для каждого из ваших конкретных классов - это путь.

try {
    // find the type of the field, and look for a String constructor
    return fieldType.getType().getConstructor(String.class).newInstance(sqlArg);
} catch (Exception e) {
    throw SqlExceptionUtil.create("could not call the string constructor on "
        + fieldType.getType(), e);
}
...