Android 如何修复在房间数据库中保存自定义数据类型列表时出现的错误
我试图在room数据库中保存一个自定义数据类型的列表,实际上,我希望其中一列应该包含所有事务的列表,表明我不需要两个表 account.ktAndroid 如何修复在房间数据库中保存自定义数据类型列表时出现的错误,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
@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
}