Definir un Objeto Realm
Para definir un objeto Realm en su aplicación, cree una subclase de RealmObject o implementar RealmModel.
Importante
Todos los objetos Realm deben proporcionar un constructor vacío.
Todos los objetos de Realm deben utilizar el
publicmodificador de visibilidad en Java o el modificador de visibilidadopenen Kotlin.
Nota
Los nombres de clase están limitados a un máximo de 57 caracteres UTF-8.
Ampliar RealmObject
El siguiente bloque de código muestra un objeto Realm que describe una clase Frog. Esta clase Frog se puede almacenar en Realm porque es extends la clase RealmObject.
import io.realm.RealmObject; // To add an object to your Realm Schema, extend RealmObject public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject // providing default values for each constructor parameter // fulfills the need for an empty constructor open class Frog( var name: String? = null, var age: Int = 0, var species: String? = null, var owner: String? = null ) : RealmObject() // To add an object to your Realm Schema, extend RealmObject
Implementar RealmModel
El siguiente bloque de código muestra un objeto Realm que describe una rana. Esta clase de rana se puede almacenar en Realm porque implements es la clase RealmModel y usa la anotación @RealmClass:
import io.realm.RealmModel; import io.realm.annotations.RealmClass; public class Frog implements RealmModel { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog() {} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
Importante
Todos los objetos de Realm deben utilizar el modificador de visibilidad public.
import io.realm.RealmModel import io.realm.annotations.RealmClass open class Frog : RealmModel { var name: String? = null var age = 0 var species: String? = null var owner: String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Importante
Todos los objetos de Realm deben utilizar el modificador de visibilidad open.
Tip
Uso de métodos de RealmObject
Al crear un objeto Realm extendiendo la clase RealmObject, se puede acceder dinámicamente a los métodos de la clase RealmObject en las instancias de dicho objeto. Los objetos Realm creados implementando RealmModel pueden acceder estáticamente a esos mismos métodos a través de la clase RealmObject:
// With RealmObject frogRealmObject.isValid(); frogRealmObject.addChangeListener(listener); // With RealmModel RealmObject.isValid(frogRealmModel); RealmObject.addChangeListener(frogRealmModel, listener);
// With RealmObject frogRealmObject?.isValid frogRealmObject?.addChangeListener(listener) // With RealmModel RealmObject.isValid(frogRealmModel) RealmObject.addChangeListener(frogRealmModel, listener)
Listas
Los objetos de Realm pueden contener listas de tipos de datos que no son objetos de Realm:
A diferencia de las listas de objetos Realm, estas listas pueden contener valores nulos. Si no se deben permitir valores nulos, use la anotación @Required.
import io.realm.RealmList; import io.realm.RealmObject; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; private RealmList<String> favoriteColors; public Frog(String name, int age, String species, String owner, RealmList<String> favoriteColors) { this.name = name; this.age = age; this.species = species; this.owner = owner; this.favoriteColors = favoriteColors; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public RealmList<String> getFavoriteColors() { return favoriteColors; } public void setFavoriteColors(RealmList<String> favoriteColors) { this.favoriteColors = favoriteColors; } }
import io.realm.RealmList import io.realm.RealmObject open class Frog : RealmObject { var name: String? = null var age = 0 var species: String? = null var owner: String? = null var favoriteColors : RealmList<String>? = null constructor( name: String?, age: Int, species: String?, owner: String?, favoriteColors: RealmList<String>? ) { this.name = name this.age = age this.species = species this.owner = owner this.favoriteColors = favoriteColors } constructor() {} // RealmObject subclasses must provide an empty constructor }
Definir un campo de objeto incrustado
Realm permite anidar objetos dentro de otros objetos. Esto tiene varias ventajas:
Si se utiliza Sync, los objetos se traducen en documentos MongoDB que siguen un modelo de datos desnormalizado.
Cuando elimina un objeto que contiene otro objeto, la operación de eliminación elimina ambos objetos del reino, por lo que los objetos no utilizados no se acumulan en su archivo de reino, ocupando espacio valioso en los dispositivos móviles de los usuarios.
Para incrustar un objeto, establezca la embedded propiedad de la anotación @RealmClass en true en la clase que desea anidar dentro de otra clase:
import io.realm.RealmObject; import io.realm.annotations.RealmClass; public class Fly extends RealmObject { private String name; public Fly(String name) { this.name = name; } public Fly() {} // RealmObject subclasses must provide an empty constructor }
import io.realm.RealmObject import io.realm.annotations.RealmClass open class Fly : RealmObject { private var name: String? = null constructor(name: String?) { this.name = name } constructor() {} // RealmObject subclasses must provide an empty constructor }
Luego, cada vez que hagas referencia a esa clase desde otra clase, Realm integrará la clase referenciada dentro de la clase envolvente, como en el siguiente ejemplo:
import io.realm.RealmObject; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; private Fly lastMeal; public Frog(String name, int age, String species, String owner, Fly lastMeal) { this.name = name; this.age = age; this.species = species; this.owner = owner; this.lastMeal = lastMeal; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public Fly getLastMeal() { return lastMeal; } public void setLastMeal(Fly lastMeal) { this.lastMeal = lastMeal; } }
import io.realm.RealmObject open class Frog : RealmObject { var name: String? = null var age = 0 var species: String? = null var owner: String? = null var lastMeal: Fly? = null constructor( name: String?, age: Int, species: String?, owner: String?, lastMeal: Fly? ) { this.name = name this.age = age this.species = species this.owner = owner this.lastMeal = lastMeal } constructor() {} // RealmObject subclasses must provide an empty constructor }
Anotaciones
Utilice anotaciones para personalizar sus modelos de objetos de Realm.
Clave principal
Novedad 10.6.0 de la versión: Realm indexa automáticamente los campos de clave principal. Anteriormente, Realm solo indexaba String automáticamente las claves principales.
Realm trata los campos marcados con la anotación @PrimaryKey como claves principales para su esquema de objeto correspondiente. Las claves principales están sujetas a las siguientes limitaciones:
Puede definir solo una clave principal por esquema de objeto.
Los valores de clave primaria deben ser únicos en todas las instancias de un objeto en un realm. Intentar insertar un valor de clave primaria duplicado da como resultado una RealmPrimaryKeyConstraintException.
Los valores de la llave primaria son inmutables. Para cambiar el valor de la clave primaria de un objeto, se debe borrar el objeto original e insertar uno nuevo con un valor de clave primaria diferente.
Los objetos incrustados no pueden definir una clave principal.
Puede crear una clave principal con cualquiera de los siguientes tipos:
StringUUIDObjectIdIntegerorintLongorlongShortorshortByteorbyte[]
Los tipos no primitivos pueden contener un valor de null como clave principal, pero solo para un objeto de un tipo específico, ya que cada valor de clave principal debe ser único. Intentar insertar un objeto con una clave principal existente en un dominio generará una excepción RealmPrimaryKeyConstraintException.
Realm indexa automáticamente los campos de clave principal, lo que le permite leer y modificar objetos de manera eficiente en función de su clave principal.
No se puede cambiar el campo de clave principal de un tipo de objeto después de añadir cualquier objeto de ese tipo a un dominio. Si se usa Sync, no se puede cambiar el campo de clave principal de un objeto después de definir la clave principal en el esquema de backend.
Los objetos incrustados no pueden contener claves principales.
Opcionalmente, puede definir una clave principal para un tipo de objeto como parte del esquema del objeto con la anotación @PrimaryKey:
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.PrimaryKey open class Frog : RealmObject { var name : String? = null var age = 0 var species: String? = null var owner: String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Campos obligatorios
import io.realm.RealmObject; import io.realm.annotations.Required; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.Required open class Frog : RealmObject { var name: String? = null var age = 0 var species: String? = null var owner: String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Campos opcionales
Los campos marcados con tipos de objeto Java y tipos Kotlin que aceptan valores NULL (que terminan ? en) aceptan valores NULL por defecto. Todos los demás tipos (primitivos, tipos de objeto Kotlin que no aceptan valores NULL) son obligatorios por defecto. Puede marcar un campo que acepta valores NULL con la anotación @Required para evitar que contenga un valor NULL. Las listas RealmList nunca aceptan valores NULL, pero puede usar la @Required anotación para evitar que los objetos de una lista contengan un valor NULL, incluso si el tipo base lo permite. No puede marcar un RealmList RealmObject subtipo o como obligatorio.
Puedes realizar cualquiera de los siguientes tipos requeridos:
StringUUIDObjectIdIntegerLongShortByteorbyte[]BooleanFloatDoubleDateRealmList
Los tipos primitivos, como int y RealmList, son implícitamente obligatorios. Los campos de tipo RealmObject siempre admiten valores nulos y no pueden ser obligatorios.
Importante
Tipos y nulidad de Kotlin
En Kotlin, los tipos no aceptan valores NULL por defecto, a menos que se ? les añada explícitamente el sufijo. Solo se pueden anotar tipos que aceptan valores NULL. Usar la @Required anotación en tipos que no aceptan valores NULL provocará un error de compilación.
Los campos que aceptan valores nulos son opcionales por defecto en Realm, a menos que se especifique lo contrario con la anotación @Required. Los siguientes tipos aceptan valores nulos:
StringDateUUIDObjectIdIntegerLongShortByteorbyte[]BooleanFloatDouble
Los tipos primitivos como int y long no son nulos de manera predeterminada y no se pueden convertir en nulos, ya que no se pueden establecer en un valor nulo.
En Kotlin, los campos se consideran nulos solo si un campo está marcado como nulo con el operador Kotlin ? excepto los siguientes tipos:
StringDateUUIDObjectIdDecimal128RealmAny
Puede requerir cualquier tipo que termine con el operador ? de Kotlin, como Int?.
El tipo RealmList no es nulo de manera predeterminada y no se puede convertir en nulo.
Valores de campo predeterminados
Para asignar un valor predeterminado a un campo, utilice las funciones de lenguaje integradas para asignar valores predeterminados.
Utilice los constructores de clase para asignar valores predeterminados:
import io.realm.RealmObject; public class Frog extends RealmObject { private String name = "Kitty"; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
Asignar valores predeterminados en la declaración del campo:
import io.realm.RealmObject open class Frog : RealmObject { var name = "Kitty" var age = 0 var species: String? = null var owner: String? = null constructor(name: String, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Nota
Valores predeterminados y nulabilidad
Si bien los valores predeterminados garantizan que un objeto recién creado no pueda contener un valor de null (a menos que especifique un valor predeterminado null de), no afectan la nulidad de un campo. Para que un campo no sea nulo, consulte Campos obligatorios.
Indexar un campo
Los índices facilitan la ejecución eficiente de consultas en Realm. Sin índices, Realm debe realizar un análisis de colección (es decir, analizar todos los documentos de una colección) para seleccionar los que coinciden con una consulta. Si existe un índice adecuado para una consulta, Realm puede usarlo para limitar el número de documentos que debe inspeccionar.
Los índices son estructuras de datos especiales que almacenan una pequeña porción de los datos de un dominio de forma fácil de recorrer. El índice almacena el valor de un campo específico, ordenado según su valor. La ordenación de las entradas del índice facilita la realización de búsquedas de igualdad eficientes y consultas basadas en rangos.
Añadir un índice puede acelerar algunas consultas, pero conlleva tiempos de escritura ligeramente más lentos y sobrecarga adicional de almacenamiento y memoria. Los índices requieren espacio en el archivo de dominio, por lo que añadir un índice a una propiedad aumentará el espacio en disco que consume dicho archivo. Cada entrada de índice tiene un mínimo de 12 bytes.
Puede indexar campos con los siguientes tipos:
StringUUIDObjectIdIntegerorintLongorlongShortorshortByteorbyte[]BooleanorboolDateRealmAny
Realm crea índices para los campos anotados con @Index.
Para indexar un campo, utilice la anotación @Index:
import io.realm.RealmObject; import io.realm.annotations.Index; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.Index open class Frog : RealmObject { var name: String? = null var age = 0 var species : String? = null var owner: String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Ignorar un campo
Si no desea guardar un campo en su modelo en un reino, puede ignorar un campo.
Ignorar un campo de un modelo de objeto Realm con la anotación @Ignore:
import io.realm.RealmObject; import io.realm.annotations.Ignore; public class Frog extends RealmObject { private String name; private int age; private String species; // can you ever really own a frog persistently? private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.Ignore open class Frog : RealmObject { var name: String? = null var age = 0 var species: String? = null // can you ever really own a frog persistently? var owner : String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Nota
El SDK ignora los campos estáticos y transitorios
Los campos marcados con static o transient siempre se ignoran y no necesitan la anotación @Ignore.
Renombrar un campo
Por defecto, Realm utiliza el nombre definido en la clase del modelo para representar los campos internamente. En algunos casos, puede que desee cambiar este comportamiento:
Para facilitar el trabajo en diferentes plataformas, ya que las convenciones de nomenclatura difieren.
Para cambiar un nombre de campo en Kotlin sin forzar una migración.
Elegir un nombre interno diferente del nombre utilizado en las clases del modelo tiene las siguientes implicaciones:
Las migraciones deben utilizar el nombre interno al crear clases y campos.
Los errores de esquema informados utilizarán el nombre interno.
Utilice la anotación @RealmField para cambiar el nombre de un campo:
import io.realm.RealmObject; import io.realm.annotations.RealmField; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.RealmField open class Frog : RealmObject { var name: String? = null var age = 0 var species: String? = null var owner: String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Alternativamente, también puede asignar una política de nombres en los niveles de módulo o clase para cambiar la forma en que Realm interpreta los nombres de campo.
Puede definir una política de nombres a nivel de módulo, que afectará a todas las clases incluidas en el módulo:
import io.realm.annotations.RealmModule; import io.realm.annotations.RealmNamingPolicy; public class MyModule { }
import io.realm.annotations.RealmModule import io.realm.annotations.RealmNamingPolicy open class MyModule
También puede definir una política de nombres a nivel de clase, que anule las configuraciones a nivel de módulo:
import io.realm.RealmObject; import io.realm.annotations.RealmClass; import io.realm.annotations.RealmNamingPolicy; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.RealmClass import io.realm.annotations.RealmNamingPolicy open class Frog : RealmObject { var name: String? = null var age = 0 var species: String? = null var owner: String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Cambiar el nombre de una clase
De forma predeterminada, Realm usa el nombre definido en la clase del modelo para representar las clases internamente. En algunos casos, podría ser conveniente cambiar este comportamiento:
Para admitir múltiples clases de modelos con el mismo nombre simple en diferentes paquetes.
Para facilitar el trabajo en diferentes plataformas, ya que las convenciones de nomenclatura difieren.
Para utilizar un nombre de clase que sea más largo que el límite de caracteres 57 impuesto por Realm.
Para cambiar un nombre de clase en Kotlin sin forzar una migración.
Utilice la anotación @RealmClass para cambiar el nombre de una clase:
import io.realm.RealmObject; import io.realm.annotations.RealmClass; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.RealmClass open class Frog : RealmObject { var name: String? = null var age = 0 var species: String? = null var owner: String? = null constructor(name: String?, age: Int, species: String?, owner: String?) { this.name = name this.age = age this.species = species this.owner = owner } constructor() {} // RealmObject subclasses must provide an empty constructor }
Omitir clases de su esquema de reino
De forma predeterminada, el esquema de dominio de su aplicación incluye todas las clases que extienden RealmObject. Si solo desea incluir un subconjunto de clases que extienden RealmObject en su esquema de dominio, puede incluir ese subconjunto de clases en un módulo y abrir su dominio usando ese módulo:
import io.realm.annotations.RealmModule; public class MyModule { }
import io.realm.annotations.RealmModule open class MyModule