Android 如何修复在房间数据库中保存自定义数据类型列表时出现的错误

Android 如何修复在房间数据库中保存自定义数据类型列表时出现的错误,android,android-room,Android,Android Room,我试图在room数据库中保存一个自定义数据类型的列表,实际上,我希望其中一列应该包含所有事务的列表,表明我不需要两个表 account.kt @Entity(tableName = "account_table") data class account( @ColumnInfo(name="name") val name:String, @ColumnInfo(name="transaction") val transactions:List<tra

我试图在room数据库中保存一个自定义数据类型的列表,实际上,我希望其中一列应该包含所有事务的列表,表明我不需要两个表

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
}

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

)

@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>

}

现在,当我运行代码时,我得到一个错误

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).


我觉得在
Dao
文件中会有一些类型转换器的代码,因为我正在访问
List

例如,列表、模型、模型列表等。当您想要存储一些特殊的类型对象时,例如在数据库中,您可以使用类型转换器。将自定义对象类型转换为已知的数据库类型。这是Room持久库最有用的功能

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>

)
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)
    }

}
和接口帐户DAO:

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

长话短说:您应该添加一个新表。房间是专门为您使用一个单独的桌子而建造的,这样做会牺牲性能和可读性。相反,您应该定义:

@Entity(
    ForeignKey(
        parentColumns = ["account_id"],
        entityColumns = ["account_id"],
        entity = Account::class,
        onDelete = ForeignKey.CASCADE, // if you delete the account, transactions are 
                                       //deleted as well
        // you can add an onUpdate cascade, but you shouldn't update account numbers at 
        //all in my opinion      
        
    ) // you'll also want add indexes on (accountId, transactionId), (accountId, date) as well
)
data class Transaction(
    @PrimaryKey(autoGenerate = true)
    val transactionId : Int,
    @ColumnInfo(name="account_id")
    val accountId : Int,
    val amount:Float,
    val description:String,
    val date:String
)
现在,您只需在“帐户”下添加:

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

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


    @Relation(
        parentColumn = "account_id", 
        entity_column="account_id", 
        entity=Transaction:class
    )
    val transactions:List<Transaction>

){
    @PrimaryKey(autoGenerate = true)@ColumnInfo(name="account_id")
    val accountId:Int=0
}
@实体(tableName=“account\u table”)
数据类帐户(
@ColumnInfo(name=“name”)
val name:String,
@关系(
parentColumn=“帐户\u id”,
entity_column=“账户id”,
实体=事务:类
)
val事务:列表
){
@PrimaryKey(autoGenerate=true)@ColumnInfo(name=“account\u id”)
val accountId:Int=0
}

我已经添加了代码,但仍然有一个错误
错误:无法确定如何将此字段保存到数据库中。可以考虑为其添加类型转换器。private final java.util.List transactions=null我已经编辑了问题,请查看@KasımÖzdemirmmust be fun getTransaction(id:Int):列表我已经在@ColumnInfo(name=“transaction”)顶部添加了类型转换器。如果需要,您可以添加行首的“抽象类accountsDatabase:RoomDatabase(){”代码带红色下划线,显示“注释不适用于目标值参数”和“
公共构造函数TypeConvertor()定义的androids.room.TypeConvertor”的参数过多
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)
        }
}
@Entity(
    ForeignKey(
        parentColumns = ["account_id"],
        entityColumns = ["account_id"],
        entity = Account::class,
        onDelete = ForeignKey.CASCADE, // if you delete the account, transactions are 
                                       //deleted as well
        // you can add an onUpdate cascade, but you shouldn't update account numbers at 
        //all in my opinion      
        
    ) // you'll also want add indexes on (accountId, transactionId), (accountId, date) as well
)
data class Transaction(
    @PrimaryKey(autoGenerate = true)
    val transactionId : Int,
    @ColumnInfo(name="account_id")
    val accountId : Int,
    val amount:Float,
    val description:String,
    val date:String
)
@Entity(tableName = "account_table")
data class account(

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


    @Relation(
        parentColumn = "account_id", 
        entity_column="account_id", 
        entity=Transaction:class
    )
    val transactions:List<Transaction>

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