Android 房间 Kotlin 内部连接
Android Room Kotlin inner join
我有两个实体
帐户:
@Entity(tableName = "accounts",foreignKeys = arrayOf(
ForeignKey(
entity = Currency::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("currencyId"),
onDelete = ForeignKey.CASCADE
)
))
data class Account (
@PrimaryKey(autoGenerate = true)
var id:Int=0,
@ColumnInfo(name="name")
var accountName:String,
@ColumnInfo(name = "balance")
var initialBalance:Double,
var currencyId:Int,
var date:Date,
var isDefault:Boolean=true
){
constructor():this(0,"",0.0,0,Date(),false)
}
和货币:
@Entity(tableName = "currencies")
data class Currency(
@PrimaryKey(autoGenerate = true)
var id:Int=0,
@ColumnInfo(name="name")
var currencyName:String,
@ColumnInfo(name="code")
var currencyCode:String
)
{
constructor():this(0,"","")
override fun toString(): String =currencyCode
}
我想在 account
中嵌入一个 currency
对象。如您所见,我在 currencies
和 accounts
之间建立了一对多的关系。当我查询 accounts
实体时,我也想查看其货币。
我尝试在 account
实体中添加一个 @Embedded
字段,但它不起作用 显然我误解了一些东西 ,该字段返回 null "No exception just null"。如果可以在account
对象中"flatten"currency
对象,这样就更好了。
所有这一切的重点是,我想显示 RecyclerView
中的所有帐户及其货币信息。我现在在 @Embedded
和 @Relation
之间感到困惑。任何帮助将不胜感激。
编辑
我不知道这是否有帮助:
这是我的 AccountDao
:
@Dao
interface AccountDao {
@Insert
fun insertAll(items:Array<Account>)
@Update
fun update(item:Account)
@Delete
fun delete(item:Account)
@Query("select * from accounts")
fun getAll():LiveData<Array<Account>>
}
我设法让它工作了。解决方案是创建一个单独的(POJO 或 POKO 随便什么)class,我称之为 AccountModel
:
class AccountModel{
var accountId:Int = 0
var accountName:String = ""
var accountInitialBalance:Double = 0.0
var accountCreationDate: Date = Date()
var currencyId:Int = 0
var currencyCode:String = ""
var isDefaultAccount:Boolean = false
constructor()
constructor(id:Int,name:String,balance:Double,date:Date,currencyId:Int,currencyCode:String,isDefault:Boolean){
this.accountId = id
this.accountName = name
this.accountInitialBalance = balance
this.accountCreationDate = date
this.currencyId = currencyId
this.currencyCode = currencyCode
this.isDefaultAccount= isDefault
}
fun toAccount():Account = Account(this.accountId,this.accountName,this.accountInitialBalance,this.currencyId,this.accountCreationDate,this.isDefaultAccount)
}
然后,构造查询以执行正常的 inner join
,就好像您正在对普通的 SQL 数据库执行 inner join
一样。像这样:
@Query("select accounts.id as accountId," +
"accounts.name as accountName," +
"accounts.balance as accountInitialBalance," +
"accounts.currencyId," +
"accounts.date as accountCreationDate," +
"accounts.isDefault as isDefaultAccount," +
"currencies.code as currencyCode " +
"from accounts inner join currencies on accounts.currencyId=currencies.id")
fun getAll():LiveData<Array<AccountModel>>
显然,您可以使用 as x
将此列投影到返回对象中的 x
字段,如您所知,在数据库中该列是 accounts.id
但在我的 AccountModel
这是一个 accountId
.
Google Room 真正令人印象深刻的是,即使我添加了一个非常聪明的 Account
对象,我也能够获得 AccountModel
的 LiveData
。
我不会推荐上述方法,因为您最终会编写相同的属性(重复自己),也就是样板代码。
按以下方式使用 @Embedded and Relation 注释,您的代码很可能如下所示:
data class AccountWithCurrency (
@Embedded
var account: Account? = null,
@Relation(parentColumn = "id", entityColumn = "currencyId")
var currency: List<Currency>? = null,
){
constructor() : this(Account(), emptyList())
}
我有两个实体 帐户:
@Entity(tableName = "accounts",foreignKeys = arrayOf(
ForeignKey(
entity = Currency::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("currencyId"),
onDelete = ForeignKey.CASCADE
)
))
data class Account (
@PrimaryKey(autoGenerate = true)
var id:Int=0,
@ColumnInfo(name="name")
var accountName:String,
@ColumnInfo(name = "balance")
var initialBalance:Double,
var currencyId:Int,
var date:Date,
var isDefault:Boolean=true
){
constructor():this(0,"",0.0,0,Date(),false)
}
和货币:
@Entity(tableName = "currencies")
data class Currency(
@PrimaryKey(autoGenerate = true)
var id:Int=0,
@ColumnInfo(name="name")
var currencyName:String,
@ColumnInfo(name="code")
var currencyCode:String
)
{
constructor():this(0,"","")
override fun toString(): String =currencyCode
}
我想在 account
中嵌入一个 currency
对象。如您所见,我在 currencies
和 accounts
之间建立了一对多的关系。当我查询 accounts
实体时,我也想查看其货币。
我尝试在 account
实体中添加一个 @Embedded
字段,但它不起作用 显然我误解了一些东西 ,该字段返回 null "No exception just null"。如果可以在account
对象中"flatten"currency
对象,这样就更好了。
所有这一切的重点是,我想显示 RecyclerView
中的所有帐户及其货币信息。我现在在 @Embedded
和 @Relation
之间感到困惑。任何帮助将不胜感激。
编辑
我不知道这是否有帮助:
这是我的 AccountDao
:
@Dao
interface AccountDao {
@Insert
fun insertAll(items:Array<Account>)
@Update
fun update(item:Account)
@Delete
fun delete(item:Account)
@Query("select * from accounts")
fun getAll():LiveData<Array<Account>>
}
我设法让它工作了。解决方案是创建一个单独的(POJO 或 POKO 随便什么)class,我称之为 AccountModel
:
class AccountModel{
var accountId:Int = 0
var accountName:String = ""
var accountInitialBalance:Double = 0.0
var accountCreationDate: Date = Date()
var currencyId:Int = 0
var currencyCode:String = ""
var isDefaultAccount:Boolean = false
constructor()
constructor(id:Int,name:String,balance:Double,date:Date,currencyId:Int,currencyCode:String,isDefault:Boolean){
this.accountId = id
this.accountName = name
this.accountInitialBalance = balance
this.accountCreationDate = date
this.currencyId = currencyId
this.currencyCode = currencyCode
this.isDefaultAccount= isDefault
}
fun toAccount():Account = Account(this.accountId,this.accountName,this.accountInitialBalance,this.currencyId,this.accountCreationDate,this.isDefaultAccount)
}
然后,构造查询以执行正常的 inner join
,就好像您正在对普通的 SQL 数据库执行 inner join
一样。像这样:
@Query("select accounts.id as accountId," +
"accounts.name as accountName," +
"accounts.balance as accountInitialBalance," +
"accounts.currencyId," +
"accounts.date as accountCreationDate," +
"accounts.isDefault as isDefaultAccount," +
"currencies.code as currencyCode " +
"from accounts inner join currencies on accounts.currencyId=currencies.id")
fun getAll():LiveData<Array<AccountModel>>
显然,您可以使用 as x
将此列投影到返回对象中的 x
字段,如您所知,在数据库中该列是 accounts.id
但在我的 AccountModel
这是一个 accountId
.
Google Room 真正令人印象深刻的是,即使我添加了一个非常聪明的 Account
对象,我也能够获得 AccountModel
的 LiveData
。
我不会推荐上述方法,因为您最终会编写相同的属性(重复自己),也就是样板代码。
按以下方式使用 @Embedded and Relation 注释,您的代码很可能如下所示:
data class AccountWithCurrency (
@Embedded
var account: Account? = null,
@Relation(parentColumn = "id", entityColumn = "currencyId")
var currency: List<Currency>? = null,
){
constructor() : this(Account(), emptyList())
}