Implementando la equivalencia de objetos Room sin clave principal agnóstica.
Considere la siguiente simple data class
que se utiliza como una Room @Entity
@Entity
data class SimpleDataClass(
val name: String,
val timestamp: String,
val isInvalid: Boolean = false,
@PrimaryKey(autoGenerate = true) val id: Int = 0
)
La funcionalidad que estoy tratando de implementar es que dos objetos de tipo SimpleDataClass
deben considerarse iguales si todas sus propiedades son iguales, sin importar su id
(que solo se agrega a la estructura de la clase porque se almacenará en una base de datos). Por ejemplo, el timestamp
solo almacena el día del mes y el usuario hizo lo mismo durante muchos meses.
Tenga en cuenta que, como registros de base de datos, deben considerarse por separado, ya que el usuario realmente generó dos registros y, por lo tanto, tienen claves primarias incrementadas automáticamente diferentes.
Esto se puede lograr escribiendo un método equals
explícito que ignore la comparación de id
. Sin embargo, también sería necesario escribir otros métodos de comparación como hashCode
y toString
, los cuales trato de evitar (permitiendo que el compilador los genere).
Para permitir que el compilador ignore id
, seguí el consejo aquí.
@Entity
data class SimpleDataClass(
val name: String,
val timestamp: String,
val isInvalid: Boolean = false,
) {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
}
Tenga en cuenta que id
ahora es una variable var
para permitir su modificación.
Esto logra lo que buscaba, excepto que rompe la función de copiado. Cuando se copia un registro leído de la base de datos como un objeto SimpleDataClass
(a través de simpleDataClass.copy()
), su id
no se transfiere a la copia. Para remediar esto, estoy usando:
old.copy(/*cambiar algunos parámetros, o no*/).also { it.id = old.id }
Ninguno de los métodos parece ser satisfactorio. ¿Cómo se puede lograr esto?
davy.ai
Para lograr la funcionalidad de considerar dos objetos
SimpleDataClass
iguales si todas sus propiedades son iguales sin importar el campoid
, puedes modificar la claseSimpleDataClass
de la siguiente manera:Esta implementación sobrescribe las funciones
equals
yhashCode
de la claseSimpleDataClass
para comparar únicamente las propiedadesname
,timestamp
yisInvalid
, y no la propiedadid
. De esta manera, dos objetosSimpleDataClass
que tengan los mismos valores paraname
,timestamp
eisInvalid
se considerarán iguales. Ten en cuenta que la propiedadid
se deja tal cual, ya queRoom
requiere que el campo@PrimaryKey
esté presente.Con esta implementación, no será necesario modificar el campo
id
por separado al copiar los objetosSimpleDataClass
. Sin embargo, al consultar la base de datos de Room, deberás utilizar el métododistinctUntilChanged()
para filtrar los objetos iguales y evitar duplicados, ya que aún tienen diferentes valores deid
en la base de datos.