How to use Android Room on entities without fields?

与世无争的帅哥 提交于 2020-02-05 04:32:09

问题


I have java objects which are are backed by a HashMap and thus do not have plain fields which can be discovered via reflection. For example:

public class City {
    private final HashMap<String, String> internalMap = new HashMap<String, String>();

    public String getId() {
        return internalMap.get("id");
    }

    public void setId(String id) {
        internalMap.put("id", id);
    }

    public String getName() {
        return internalMap.get("name");
    }

    public void setName(String name) {
        internalMap.put("name", name);
    }
}

I want to use classes such as this an entity in Room without having to change its structure since I have many such classes which are auto-generated using code generation tools and there are specific reasons why they need to be backed by a HashMap. Each value of the HashMap should end up as a column in my database table (the key String is an internal implementation detail). Is it possible? Seems not to be at the moment due to how fields are discovered by the annotation processor.

UPDATE:

None of the answers were at all what I was looking for. I opened a new question without mentioning HashMap since that detail was not supposed to be relevant but all the answers latched on to it. See How to use Android Room with POJOs provided by an external library? for the updated question.


回答1:


You can use TypeConverter for this. For instance, you can use serialization provided by GSON to easily convert the map to serialized state and vice versa.

class MapConverter {
    @TypeConverter
    public String fromMap(HashMap<String, String> map) {
        return new Gson().toJson(map);
    }

    @TypeConverter
    public HashMap<String, String> fromString(String serializedMap) {
        Type type = new TypeToken<HashMap<String, String>>(){}.getType();
        return gson.fromJson("serializedMap", type);
    }
}

And in your entity class:

@Entity
@TypeConverters({MapConverter.class})
public class CityEntity {
//...
private final HashMap<String, String> internalMap;
//...
}

So the converter will be available for this entity to serialize the hashmap to string and vice versa. Gson is just a possible solution, you can actually use whatever you want.




回答2:


Room has it's own set of annotations - and if you do not want to have a field mapped, you have to indicate this towards the annotation processor by annotating the POJO as it may be required; eg. @Entity without assigning a tableName, as well the @Ignore above the field to ignore:

@Entity
public class City {

    @Ignore
    private final HashMap<String, String> internalMap = new HashMap<>();

    /* concerning the second part of the question: */
    public HashMap<String, Object> toHashMap() {
        return this.internalMap;
    }
}

besides those getters have the fundamental problem, that they assume all the keys would exist, despite the HashMap might not have been populated with all (or any) of those keys. and it's absurd to represent a city with two different types of object - while one has full control over which fields are being mapped and which are being ignored (one possible approach does not have to exclude the other here)... a method to return the HashMap might be useful, eg. in order to insert that into Firebase.

I'd rather go for fields holding the values, while nevertheless being able to return a HashMap:

@Entity(tableName = "cities")
public class City {

    @ColumnInfo(name = "cityId")
    @PrimaryKey(autoGenerate = true)
    private int cityId = -1;

    @ColumnInfo(name = "cityName")
    private String cityName = null;

    ...

    /* concerning the second part of the question: */
    public HashMap<String, Object> toHashMap() {
        HashMap<String, Object> values = new HashMap<>();
        if(this.cityId   !=   -1) {values.put(  "id", this.cityId);}
        if(this.cityName != null) {values.put("name", this.cityName);}
        return values;
    }
}

such a toHashMap() method also provides control, which fields the returned HashMap shall contain, while the example with the TypeConverter & GSON would (as it is) convert the whole HashMap.



来源:https://stackoverflow.com/questions/51902935/how-to-use-android-room-on-entities-without-fields

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!