2

我愿意尝试来自 Android 的新 Room Library,但遇到了以下错误:

错误:(19, 29) 错误:无法弄清楚如何将此字段保存到数据库中。您可以考虑为其添加类型转换器。

此错误涉及以下类成员:

private HashSet<String> fruits;

我有以下课程:

@Entity(tableName = "SchoolLunches")
public class SchoolLunch {

    @PrimaryKey(autoGenerate = true)
    private int lunchId;

    private boolean isFresh;

    private boolean containsMeat;

    private HashSet<String> fruits;

    public int getLunchId() {
        return lunchId;
    }

    public void setLunchId(int lunchId) {
        this.lunchId = lunchId;
    }

    public boolean isFresh() {
        return isFresh;
    }

    public void setFresh(boolean fresh) {
        isFresh = fresh;
    }

    public boolean isContainsMeat() {
        return containsMeat;
    }

    public void setContainsMeat(boolean containsMeat) {
        this.containsMeat = containsMeat;
    }

    public HashSet<String> getFruits() {
        return fruits;
    }

    public void setFruits(HashSet<String> fruits) {
        this.fruits = fruits;
    }

此外,还有一个相对的 DAO 类:

@Dao
public interface SchoolLunchDAO {

    @Query("SELECT * FROM SchoolLunches")
    List<SchoolLunch> getAll();

    @Insert
    void insertAll(SchoolLunch... schoolLunches);

    @Query("DELETE FROM SchoolLunches")
    void deleteAll();
}

由于我正在努力成为一名非常优秀的开发人员,因此我编写了一个单元测试如下:

@Test
public void singleEntityTest() {
        HashSet<String> fruitSet = new HashSet<>();
        fruitSet.add("Apple");
        fruitSet.add("Orange");

        SchoolLunch schoolLunch = new SchoolLunch();
        schoolLunch.setContainsMeat(false);
        schoolLunch.setFresh(true);
        schoolLunch.setFruits(fruitSet);

        schoolLunchDAO.insertAll(schoolLunch);

        List<SchoolLunch> schoolLunches = schoolLunchDAO.getAll();
        assertEquals(schoolLunches.size(), 1);

        SchoolLunch extractedSchoolLunch = schoolLunches.get(0);
        assertEquals(false, extractedSchoolLunch.isContainsMeat());
        assertEquals(true, extractedSchoolLunch.isFresh());
        assertEquals(2, extractedSchoolLunch.getFruits().size());
 }

我应该在这里做什么?

4

2 回答 2

2

我应该在这里做什么?

您可以按照错误消息的建议创建一个类型转换器。Room 不知道如何持久化 a HashSet<String>、 aRestaurant或其他任意对象。

第 1 步:确定您想要转换HashSet<String>成的基本类型(例如,a String

步骤#2:编写一个带有public static类型转换方法的类,用 注释@TypeConverter,以某种安全的方式进行转换(例如HashSet<String>to StringStringto HashSet<String>)(例如,使用 Gson,将您的格式设置String为 JSON)

第 3 步:@TypeConverters向您的或其他范围添加注释RoomDatabase,以向 Room 教授您的@TypeConverter方法

例如,这里有一对类型转换器方法,用于将 a 转换为Set<String>常规String,使用 JSON 作为String.

  @TypeConverter
  public static String fromStringSet(Set<String> strings) {
    if (strings==null) {
      return(null);
    }

    StringWriter result=new StringWriter();
    JsonWriter json=new JsonWriter(result);

    try {
      json.beginArray();

      for (String s : strings) {
        json.value(s);
      }

      json.endArray();
      json.close();
    }
    catch (IOException e) {
      Log.e(TAG, "Exception creating JSON", e);
    }

    return(result.toString());
  }

  @TypeConverter
  public static Set<String> toStringSet(String strings) {
    if (strings==null) {
      return(null);
    }

    StringReader reader=new StringReader(strings);
    JsonReader json=new JsonReader(reader);
    HashSet<String> result=new HashSet<>();

    try {
      json.beginArray();

      while (json.hasNext()) {
        result.add(json.nextString());
      }

      json.endArray();
    }
    catch (IOException e) {
      Log.e(TAG, "Exception parsing JSON", e);
    }

    return(result);
  }
于 2017-06-19T15:18:30.207 回答
1

我创建了以下类,现在它可以工作了。谢谢你,CommonsWare!

public class Converters {

    private static final String SEPARATOR = ",";

    @TypeConverter
    public static HashSet<String> fromString(String valueAsString) {
        HashSet<String> hashSet = new HashSet<>();
        if (valueAsString != null && !valueAsString.isEmpty()) {
            String[] values = valueAsString.split(SEPARATOR);
            hashSet.addAll(Arrays.asList(values));
        }
        return hashSet;
    }

    @TypeConverter
    public static String hashSetToString(HashSet<String> hashSet) {
        StringBuilder stringBuilder = new StringBuilder();
        for (String currentElement : hashSet) {
            stringBuilder.append(currentElement);
            stringBuilder.append(SEPARATOR);
        }
        return stringBuilder.toString();
    }

}
于 2017-06-20T10:51:40.827 回答