Java Android Room 数据库:如何处理实体中的 Arraylist?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44986626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:49:30  来源:igfitidea点击:

Android Room Database: How to handle Arraylist in an Entity?

javaandroidandroid-room

提问by Tushar Gogna

I just implemented Room for offline data saving. But in an Entity class, I am getting the following error:

我刚刚实现了用于离线数据保存的 Room。但是在实体类中,我收到以下错误:

Error:(27, 30) error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.

And the class is as following:

课程如下:

@Entity(tableName = "firstPageData")
public class MainActivityData {
@PrimaryKey
private String userId;

@ColumnInfo(name = "item1_id")
private String itemOneId;

@ColumnInfo(name = "item2_id")
private String itemTwoId;

   // THIS IS CAUSING THE ERROR... BASICALLY IT ISN'T READING ARRAYS
   @ColumnInfo(name = "mylist_array")
    private ArrayList<MyListItems> myListItems;

public String getUserId() {
    return userId;
}

public void setUserId(String userId) {
    this.userId = userId;
}


public ArrayList<MyListItems> getMyListItems() {
    return myListItems;
}

public void setCheckListItems(ArrayList<MyListItems> myListItems) {
    this.myListItems = myListItems;
}
}

So basically I want to save the ArrayList in the database but I was not able to find anything relevant to it. Can you guide me regarding how to save an Array using Room?

所以基本上我想将 ArrayList 保存在数据库中,但我找不到与之相关的任何内容。你能指导我如何使用 Room 保存数组吗?

NOTE: MyListItems Pojo class contains 2 Strings (as of now)

注意:MyListItems Pojo 类包含 2 个字符串(截至目前)

Thanks in advance.

提前致谢。

采纳答案by CommonsWare

Option #1: Have MyListItemsbe an @Entity, as MainActivityDatais. MyListItemswould set up a @ForeignKeyback to MainActivityData. In this case, though, MainActivityDatacannot have private ArrayList<MyListItems> myListItems, as in Room, entities do not refer to other entities. A view model or similar POJO construct could have a MainActivityDataand its associated ArrayList<MyListItems>, though.

选项#1:MyListItems@Entity原样MainActivityData是一个。MyListItems会设置一个@ForeignKeyMainActivityData。但是,在这种情况下,MainActivityData不能有private ArrayList<MyListItems> myListItems,就像在 Room 中一样,实体不引用其他实体。但是,视图模型或类似的 POJO 构造可以具有 aMainActivityData及其关联的ArrayList<MyListItems>

Option #2: Set up a pair of @TypeConvertermethods to convert ArrayList<MyListItems>to and from some basic type (e.g., a String, such as by using JSON as a storage format). Now, MainActivityDatacan have its ArrayList<MyListItems>directly. However, there will be no separate table for MyListItems, and so you cannot query on MyListItemsvery well.

选项#2:设置一对@TypeConverter方法来ArrayList<MyListItems>与某些基本类型(例如, a String,例如通过使用 JSON 作为存储格式)进行转换。现在,MainActivityData可以ArrayList<MyListItems>直接拥有它。但是,将没有单独的表MyListItems,因此您不能很好地查询MyListItems

回答by Amit Bhandari

Type Converterare made specifically for that. In your case, you can use code snippet given below to store data in DB.

Type Converter是专门为此制作的。在您的情况下,您可以使用下面给出的代码片段将数据存储在数据库中。

public class Converters {
@TypeConverter
public static ArrayList<String> fromString(String value) {
    Type listType = new TypeToken<ArrayList<String>>() {}.getType();
    return new Gson().fromJson(value, listType);
}

@TypeConverter
public static String fromArrayList(ArrayList<String> list) {
    Gson gson = new Gson();
    String json = gson.toJson(list);
    return json;
}
}

And mention this class in your Room DB like this

并像这样在您的 Room DB 中提及此类

@Database (entities = {MainActivityData.class},version = 1)
@TypeConverters({Converters.class})

More info here

更多信息在这里

回答by live-love

Had the same error message as described above. I would like to add: if you get this error message in a @Query, you should add @TypeConverters above the @Query annotation.

有与上述相同的错误消息。我想补充一点:如果您在@Query 中收到此错误消息,您应该在@Query 注释上方添加@TypeConverters。

Example:

例子:

@TypeConverters(DateConverter.class)
@Query("update myTable set myDate=:myDate  where id = :myId")
void updateStats(int myId, Date myDate);

....

....

public class DateConverter {

    @TypeConverter
    public static Date toDate(Long timestamp) {
        return timestamp == null ? null : new Date(timestamp);
    }

    @TypeConverter
    public static Long toTimestamp(Date date) {
        return date == null ? null : date.getTime();
    }
}

回答by Manohar Reddy

Kotlinversion for type converter:

类型转换器的Kotlin版本:

 class Converters {

    @TypeConverter
    fun listToJson(value: List<JobWorkHistory>?) = Gson().toJson(value)

    @TypeConverter
    fun jsonToList(value: String) = Gson().fromJson(value, Array<JobWorkHistory>::class.java).toList()
}

I Used JobWorkHistoryobject for my purpose, use the object of your own

JobWorkHistory为我的目的使用了对象,使用你自己的对象

@Database(entities = arrayOf(JobDetailFile::class, JobResponse::class), version = 1)
@TypeConverters(Converters::class)
abstract class MyRoomDataBase : RoomDatabase() {
     abstract fun attachmentsDao(): AttachmentsDao
}

回答by Derrick Njeru

This is how i handle List conversion

这就是我处理列表转换的方式

public class GenreConverter {
@TypeConverter
public List<Integer> gettingListFromString(String genreIds) {
    List<Integer> list = new ArrayList<>();

    String[] array = genreIds.split(",");

    for (String s : array) {
       if (!s.isEmpty()) {
           list.add(Integer.parseInt(s));
       }
    }
    return list;
}

@TypeConverter
public String writingStringFromList(List<Integer> list) {
    String genreIds = "";
    for (int i : list) {
        genreIds += "," + i;
    }
    return genreIds;
}}

And then on the database i do as shown below

然后在数据库上我做如下所示

@Database(entities = {MovieEntry.class}, version = 1)
@TypeConverters(GenreConverter.class)

And below is a kotlin implementation of the same;

下面是相同的 kotlin 实现;

class GenreConverter {
@TypeConverter
fun gettingListFromString(genreIds: String): List<Int> {
    val list = mutableListOf<Int>()

    val array = genreIds.split(",".toRegex()).dropLastWhile {
        it.isEmpty()
    }.toTypedArray()

    for (s in array) {
        if (s.isNotEmpty()) {
            list.add(s.toInt())
        }
    }
    return list
}

@TypeConverter
fun writingStringFromList(list: List<Int>): String {
    var genreIds=""
    for (i in list) genreIds += ",$i"
    return genreIds
}}

回答by Fidan Bacaj

Use official solution from room, @Embedded annotation :

使用房间的官方解决方案,@Embedded 注释:

@Embedded(prefix = "mylist_array") private ArrayList<MyListItems> myListItems

回答by abitcode

Adding @TypeConverterswith the converter class as params

添加@TypeConverters转换器类作为参数

to Database & to the Dao class, made my queries work

到数据库和 Dao 类,使我的查询工作

回答by Daniel Wilson

This answer uses Kotin to split by comma and construct the comma delineated string. The comma needs to go at the end of all but the last element, so this will handle single element lists as well.

此答案使用 Kotin 以逗号分隔并构造以逗号分隔的字符串。逗号需要放在除最后一个元素之外的所有元素的末尾,因此这也将处理单个元素列表。

object StringListConverter {
        @TypeConverter
        @JvmStatic
        fun toList(strings: String): List<String> {
            val list = mutableListOf<String>()
            val array = strings.split(",")
            for (s in array) {
                list.add(s)
            }
            return list
        }

        @TypeConverter
        @JvmStatic
        fun toString(strings: List<String>): String {
            var result = ""
            strings.forEachIndexed { index, element ->
                result += element
                if(index != (strings.size-1)){
                    result += ","
                }
            }
            return result
        }
    }

回答by Dokuzov

Json conversions don't scale well in terms of memory allocation.I'd rather go for something similar to responses above with some nullability.

Json 转换在内存分配方面不能很好地扩展。我宁愿选择与上面的响应类似的东西,但具有一些可空性。

class Converters {
    @TypeConverter
    fun stringAsStringList(strings: String?): List<String> {
        val list = mutableListOf<String>()
        strings
            ?.split(",")
            ?.forEach {
                list.add(it)
            }

        return list
    }

    @TypeConverter
    fun stringListAsString(strings: List<String>?): String {
        var result = ""
        strings?.forEach { element ->
            result += "$element,"
        }
        return result.removeSuffix(",")
    }
}

For simple data types the above can be used, otherwise for complex datatypes Room provides Embedded

对于简单的数据类型可以使用上面的,否则对于复杂的数据类型 Room 提供Embedded

回答by Nitin Misra

Better version of List<String>converter

更好的List<String>转换器版本

class StringListConverter {
    @TypeConverter
    fun fromString(stringListString: String): List<String> {
        return stringListString.split(",").map { it }
    }

    @TypeConverter
    fun toString(stringList: List<String>): String {
        return stringList.joinToString(separator = ",")
    }
}