I'm working with Kotlin + Jetpack Compose. I'm also using Room, Hilt, MVVM, UiStates, etc.
I have an entity Game
, an entity Round
and an entity Turn
.
The relationships between them are:
When I am working in TurnViewModel
for example, I need to get some info from the entity Game
, sometimes I even need to update it. What is the most efficient way to do this?
It would be great to get it trough dot notation, something like this: currentTurn.round.game.some_game_field
, but since I'm used to work with Odoo framework, I'm a newbie and I don't know how to do it, even if that's the best way to work here.
Currently my Turn
entity looks like this:
@Entity(
tableName = "turn",
foreignKeys = [
ForeignKey(
entity = Round::class,
parentColumns = ["id"],
childColumns = ["roundId"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Player::class,
parentColumns = ["id"],
childColumns = ["player1Id"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Player::class,
parentColumns = ["id"],
childColumns = ["player2Id"],
onDelete = ForeignKey.CASCADE
)
]
)
data class Turn(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val roundId: Long,
val player1Id: Long,
val player2Id: Long,
)
data class TurnWithCards(
@Embedded val turn: Turn,
@Relation(
parentColumn = "id",
entityColumn = "id",
associateBy = Junction(
TurnCardRel::class,
parentColumn = "turnId",
entityColumn = "cardId"
)
)
val cards: List<Card>
)
However, I find some problems here. If if create an object Turn
, I only have the roundId
which is a Long
... Should I get the Game
through DAO queries from the repository?
And on the other hand, I have the object TurnWithCards
, which allows me to access easily to a list of object Card
, but isn't there a way to have all data centralised in one object? I mean, maybe I need to add another list of objects, like Score
for example, and should I create another data class TurnWithScores
? Can't I have something like this?
data class TurnORM(
...
val round: Round,
val game: Game,
val player1: Player,
val player2: Player,
val cards: List<Card>
)
If you see that this is a nosense, you can tell me, I only want to do this following good practice since I'm learning.
I'm working with Kotlin + Jetpack Compose. I'm also using Room, Hilt, MVVM, UiStates, etc.
I have an entity Game
, an entity Round
and an entity Turn
.
The relationships between them are:
When I am working in TurnViewModel
for example, I need to get some info from the entity Game
, sometimes I even need to update it. What is the most efficient way to do this?
It would be great to get it trough dot notation, something like this: currentTurn.round.game.some_game_field
, but since I'm used to work with Odoo framework, I'm a newbie and I don't know how to do it, even if that's the best way to work here.
Currently my Turn
entity looks like this:
@Entity(
tableName = "turn",
foreignKeys = [
ForeignKey(
entity = Round::class,
parentColumns = ["id"],
childColumns = ["roundId"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Player::class,
parentColumns = ["id"],
childColumns = ["player1Id"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Player::class,
parentColumns = ["id"],
childColumns = ["player2Id"],
onDelete = ForeignKey.CASCADE
)
]
)
data class Turn(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val roundId: Long,
val player1Id: Long,
val player2Id: Long,
)
data class TurnWithCards(
@Embedded val turn: Turn,
@Relation(
parentColumn = "id",
entityColumn = "id",
associateBy = Junction(
TurnCardRel::class,
parentColumn = "turnId",
entityColumn = "cardId"
)
)
val cards: List<Card>
)
However, I find some problems here. If if create an object Turn
, I only have the roundId
which is a Long
... Should I get the Game
through DAO queries from the repository?
And on the other hand, I have the object TurnWithCards
, which allows me to access easily to a list of object Card
, but isn't there a way to have all data centralised in one object? I mean, maybe I need to add another list of objects, like Score
for example, and should I create another data class TurnWithScores
? Can't I have something like this?
data class TurnORM(
...
val round: Round,
val game: Game,
val player1: Player,
val player2: Player,
val cards: List<Card>
)
If you see that this is a nosense, you can tell me, I only want to do this following good practice since I'm learning.
What you're trying to do can be done with @Relation
and @Embedded
annotations,
but it is useless, to reload values which may not have changed, to update the view.
Creating one huge joined query is commonly not what one would like to do, despite it's possible. It's probably more handy to have some GameState
or RoundState
class (not ORM, but eventually as ViewModel
or ViewDataBinding
), which holds the current values; I mean, not to directly map the values from ORM to the GUI; and for subsequent queries, one can obtain the IDs to query for or update from there. Sometimes it is useful to directly map ORM to the GUI, sometimes not.
The object modelling itself appears unfortunate and could possibly reduced.
One could even still nest the players
into to game
, or even dissolve game
.
To provide an example of what I'm talking about:
class GameState(
// cards nested into here, as they're being held by players.
val players: ArrayList<Player>,
// rounds nested into here, as a game is a series of rounds.
val game: Game
)
Maybe take a piece of paper or a tablet PC and draw these object relations once.
Class TurnORM
is certain proof that you may have missed this initial design step.
With ORM, the object design also dictates how the database would look alike.