How to fix the error while saving list of custom data types in room database

江枫思渺然 提交于 2020-04-30 09:31:16

问题


I am trying to save a list of custom data types in room database, actually, I want one of the column should contain list of all transactions show that I don't have to two tables.

account.kt

@Entity(tableName = "account_table")
data class account(

    @ColumnInfo(name="name")
    val name:String,


    @ColumnInfo(name="transaction")

    val transactions:List<transaction>

){
    @PrimaryKey(autoGenerate = true)@ColumnInfo(name="account_id")
    val accountId:Int=0
}

transaction.kt

data class transaction(
    val amount:Float,
    val description:String,
    val date:String

)

Now when I am running the code I get an error

error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
    private final java.util.List<com.example.ledger.Database.transaction> transactions = null;

                                                                          ^D:\flutterProjects\Ledger\app\build\tmp\kapt3\stubs\debug\com\example\ledger\Database\account.java:10: error: Cannot find setter for field.

    private final int accountId = 0;

D:\flutterProjects\Ledger\app\build\tmp\kapt3\stubs\debug\com\example\ledger\Database\accountsDao.java:19: warning: The query returns some columns [account_id, name, transaction] which are not used by com.example.ledger.Database.transaction. You can use @ColumnInfo annotation on the fields to specify the mapping. com.example.ledger.Database.transaction has some fields [amount, description, date] which are not returned by the query. If they are not supposed to be read from the result, you can mark them with @Ignore annotation. You can suppress this warning by annotating the method with @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: account_id, name, transaction. Fields in com.example.ledger.Database.transaction: amount, description, date.

    public abstract java.util.List<com.example.ledger.Database.transaction> getTransaction(int id);

                      ^D:\flutterProjects\Ledger\app\build\tmp\kapt3\stubs\debug\com\example\ledger\Database\accountsDao.java:19: error: The columns returned by the query does not have the fields [amount,description,date] in com.example.ledger.Database.transaction even though they are annotated as non-null or primitive. Columns returned by the query: [account_id,name,transaction]

    public abstract java.util.List<com.example.ledger.Database.transaction> getTransaction(int id);

                                                                            ^[WARN] Incremental annotation processing requested, but support is disabled because the following processors are not incremental: androidx.room.RoomProcessor (DYNAMIC).

EDIT

accountDao.kt

@Dao
interface accountsDao {
    @Insert
    fun Insert(account: account)

    @Delete
    fun delete(account: account)

    @Query("SELECT * FROM account_table where account_id = :id ")
    fun getTransaction(id:Int):List<transaction>

}

accountDatabase

@Database(entities = [account::class], version = 1, exportSchema = false)

abstract class accountsDatabase : RoomDatabase() {

    abstract val accountdao: accountsDao

    companion object {

        @Volatile
        private var INSTANCE: accountsDatabase? = null


        fun getInstance(context: Context): accountsDatabase? {

            synchronized(this) {
                // Copy the current value of INSTANCE to a local variable so Kotlin can smart cast.
                // Smart cast is only available to local variables.
                var instance = INSTANCE
                // If instance is `null` make a new database instance.
                if (instance == null) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        accountsDatabase::class.java,
                        "saccount_history_database"
                    )

                        .fallbackToDestructiveMigration()
                        .build()
                    // Assign INSTANCE to the newly created database.
                    INSTANCE = instance
                }
                // Return instance; smart cast to be non-null.
                return instance
            }
        }
    }


}

I feel there would some code of type convertor in Dao file because I am accessing List<transaction>


回答1:


For example, lists, models, model list etc. When you want to store some special type objects, such as in the database, you can use Type Converters. Converts your custom object type to a type known for database types. This is the most useful feature of the Room persistent library.

account.kt:

@Entity(tableName = "account_table")
data class account(

@PrimaryKey(autoGenerate = true)@ColumnInfo(name="account_id")
val accountId:Int=0,

@ColumnInfo(name="name")
val name:String,

@TypeConverters(Converters::class)
@ColumnInfo(name="transaction")
val transactions:List<transaction>

)

Converters.kt:

class Converters {

    @TypeConverter
    fun fromTransactionList(transaction: List<transaction?>?): String? {
        if (transaction == null) {
            return null
        }
        val gson = Gson()
        val type: Type = object : TypeToken<List<transaction?>?>() {}.type
        return gson.toJson(transaction, type)
    }

    @TypeConverter
    fun toTransactionList(transactionString: String?): List<transaction>? {
        if (transactionString == null) {
            return null
        }
        val gson = Gson()
        val type =
            object : TypeToken<List<transaction?>?>() {}.type
        return gson.fromJson<List<transaction>>(transactionString, type)
    }

}

You can add like this:

@Database(entities = [account::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class accountsDatabase : RoomDatabase() 

And interface accountsDao:

@Query("SELECT * FROM account_table where account_id = :id ")
fun getTransaction(id:Int):List<account>

using:

GlobalScope.launch {
   val db = accountsDatabase.getInstance(applicationContext)
   val accounts = db.accountDao().getTransaction(your_id)
   val transactions = accounts[position].transactions
   transactions?.forEach {
            Log.d("Transaction Description" ,it.description)
        }
}


来源:https://stackoverflow.com/questions/61461954/how-to-fix-the-error-while-saving-list-of-custom-data-types-in-room-database

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