Skip to main content

Implementar el almacenamiento offline seguro con SmartStore

Objetivos de aprendizaje

Después de completar esta unidad, podrá:

  • Comprender los términos y conceptos de SmartStore básicos.
  • Usar SmartStore para generar consultas SELECT.
  • Registrar, completar y gestionar los datos de SmartStore en su plataforma de destino preferida (iOS, Android, híbrida, React Native).
  • Usar SmartStore Inspector.

Uso de SmartStore para el almacenamiento offline

Los dispositivos móviles pueden perder la conexión en cualquier momento y entornos como los hospitales y aviones suelen prohibir la conexión. Para controlar estas situaciones, es importante que sus aplicaciones sigan funcionando cuando no tengan conexión. 

Mobile SDK ofrece SmartStore, una solución segura de almacenamiento offline multiproceso para dispositivos móviles. Con SmartStore, sus clientes pueden seguir trabajando con los datos en un entorno seguro, incluso si el dispositivo pierde la conexión. Cuando une SmartStore y Mobile Sync, puede mantener fácilmente los datos locales de SmartStore sincronizados con el servidor de Salesforce cuando se retoma la conectividad.

SmartStore almacena datos como documentos JSON en una base de datos de una sola tabla sencilla. Puede recuperar datos de SmartStore con métodos de ayuda de Mobile SDK o mediante consultas personalizadas usando el lenguaje Smart SQL de SmartStore.

Sopas

SmartStore almacena datos offline en colecciones lógicas llamadas sopas. Una sopa de SmartStore representa una sola tabla en la base de datos SQLite subyacente o almacén y se suele asignar a un objeto de Salesforce estándar o personalizado. Las sopas contienen elementos de sopa. Cada elemento es un objeto JSON que se refleja en una sola fila de la base de datos. Para simplificar el acceso a los datos, defina índices para cada sopa. Use estos índices para consultar la sopa con métodos auxiliares de SmartStore o el lenguaje de consulta Smart SQL de SmartStore. Además, los índices de SmartStore facilitan el trabajo mediante la compatibilidad con consultas de búsqueda de texto completo.

Es útil pensar en las sopas como tablas y en los almacenes como bases de datos. Puede definir tantas sopas como desee en una aplicación. Como conjuntos de datos independientes, las sopas no tienen relaciones predefinidas entre sí, pero puede usar uniones de Smart SQL para consultarlas. Además, en las aplicaciones nativas puede escribir en varias sopas en una transacción.

Nota

Los datos de SmartStore son volátiles. En la mayoría de los casos, su ciclo de vida está vinculado al usuario autenticado y a los estados de token de OAuth. Cuando el usuario cierra sesión en la aplicación, SmartStore elimina todos los datos de sopa asociados a dicho usuario. De forma similar, cuando el token de actualización de OAuth se revoca o caduca, el estado de la aplicación del usuario se restablece y todos los datos de SmartStore se purgan. Al diseñar su aplicación, tenga en cuenta la volatilidad de los datos de SmartStore, sobre todo si su organización establece un ciclo de vida breve para el token de actualización.

Smart SQL

SmartStore es compatible con el lenguaje de consulta Smart SQL para declaraciones SELECT de forma libre. Solo se admiten las declaraciones SELECT. Smart SQL combina todas las construcciones gramaticales SQL SELECT estándar con una sintaxis especial para hacer referencia a las sopas y los campos de sopa. Este método le permite el máximo nivel de control y flexibilidad, lo que incluye la posibilidad de usar uniones.

Sintaxis

La sintaxis es idéntica a la de la especificación SQL SELECT estándar con las siguientes adaptaciones:

Uso Sintaxis
Para especificar una columna {<soupName>:<path>}
Para especificar una tabla {<soupName>}
Para hacer referencia a toda la cadena JSON de entrada de sopa {<soupName>:_soup}
Para hacer referencia a un Id. de entrada de sopa interno {<soupName>:_soupEntryId}
Para hacer referencia a la fecha de última modificación {<soupName>:_soupLastModifiedDate}

Consultas de ejemplo

Suponga que tiene dos sopas, una llamada Empleados y otra llamada Departamentos. La sopa Empleados contiene campos estándar como los siguientes:

  • Nombre (firstName)
  • Apellidos (lastName)
  • Código de departamento (deptCode)
  • ID. de empleado (employeeId)
  • ID. de gestor (managerId)

La sopa Departamentos contiene lo siguiente:

  • Nombre (name)
  • Código de departamento (deptCode)

Estos son algunos ejemplos de consultas Smart SQL básicas que usan estas sopas:

select {employees:firstName}, {employees:lastName} 
 from {employees} order by {employees:lastName}
select {departments:name} 
 from {departments} 
 order by {departments:deptCode}

Uniones

Smart SQL también permite el uso de uniones. Por ejemplo:

select {departments:name}, {employees:firstName} || ' ' || {employees:lastName}  
 from {employees}, {departments}  
 where {departments:deptCode} = {employees:deptCode}  
 order by {departments:name}, {employees:lastName}

Puede realizar incluso autouniones:

select mgr.{employees:lastName}, e.{employees:lastName}  
 from {employees} as mgr, {employees} as e  
 where mgr.{employees:employeeId} = e.{employees:managerId}
Nota

La realización de una unión en un índice JSON1 requiere una sintaxis ligeramente ampliada. Por ejemplo, en lugar de

select {soup1:path1} from {soup1}, {soup2}

use

select {soup1}.{soup1:path1} from {soup1}, {soup2}

Funciones de agregado

Smart SQL es compatible con el uso de funciones de agregado como:

  • COUNT
  • SUM
  • AVG

Por ejemplo:

select {account:name}, 
    count({opportunity:name}),
    sum({opportunity:amount}),
    avg({opportunity:amount}),
    {account:id},
    {opportunity:accountid} 
 from {account},
    {opportunity} 
 where {account:id} = {opportunity:accountid} 
 group by {account:name}

Registro de una sopa

Antes de utilizar una sopa, regístrela. Si la sopa no existe, se crea al registrarla. Si existe, el registro le permite el acceso. Para registrar sopas, debe crear un archivo de configuración JSON y cargarlo en el tiempo de ejecución. Un solo archivo de configuración puede definir todas las sopas de su aplicación. Mobile SDK admite archivos de configuración en aplicaciones híbridas y nativas.

Los archivos de configuración registran sopas solo en el almacén de usuario predeterminado o el almacén global predeterminado. Para usar otros almacenes denominados o almacenes externos, debe registrar las sopas mediante las API de SmartStore. Mobile SDK proporciona métodos para definir el nombre y los índices de una sopa, y luego registrarla.

Cuando registra una sopa, crea una estructura con nombre vacía en la memoria a la espera de datos. Normalmente, debe inicializar la sopa con datos de una organización de Salesforce. Para obtener los datos de Salesforce, se utiliza el mecanismo de solicitud REST estándar de Mobile SDK. Cuando llega la respuesta REST correcta, extrae los datos del objeto de respuesta y, a continuación, se actualizan e insertan en la sopa.

Durante la creación de la sopa, se pueden producir errores por varios motivos, como los siguientes:

  • Nombre de sopa no válido o incorrecto
  • Ningún índice (se debe especificar como mínimo un índice)
  • Otros errores inesperados (por ejemplo, error de la base de datos)

Estructura de sopa

Para definir una sopa, proporciona un nombre de sopa y una lista de una o varias especificaciones de índice. Los índices se basan en campos de sopa. No se le requiere proporcionar una especificación de índice para cada campo que almacena en la sopa. Por ejemplo, si está utilizando la sopa como un almacén de claves-valores sencillo, use una sola especificación de índice de tipo string. Una vez creadas las sopas, SmartStore utiliza los índices para realizar un seguimiento de cualquier operación de inserción, actualización o eliminación.

SmartStore admite los siguientes tipos de datos de índice.

  • String (Cadena)
  • integer (entero)
  • Floating (flotante)
  • Full_text (texto completo)
  • json1

Definición de índices

En aplicaciones híbridas y nativas, puede utilizar archivos de configuración para registrar sopas y definir sus índices. En aplicaciones React Native, debe utilizar código de JavaScript. Se aplican algunas reglas en cada caso.

  • Las rutas de índice incluyen la distinción entre mayúsculas y minúsculas y pueden incluir rutas compuestas, como Owner.Name.
  • No se hace un seguimiento en el índice de las entradas de índice que faltan en los campos descritos en una matriz de especificaciones de índice.
  • El tipo de índice se aplica solo al índice. Si consulta un campo indexado (por ejemplo, “select {soup:path} from {soup}”), la consulta devuelve datos del tipo que especificó en la especificación del índice.
  • Las columnas del índice no pueden contener campos nulos.
  • A partir de Mobile SDK 9.1, las rutas de índice ya no son obligatorias para los campos que se mencionan en las cláusulas SELECT o WHERE.
  • Puede especificar rutas de índice que señalan a nodos internos (nodos que no son de hoja). Puede utilizar rutas internas con consultas like y match (texto completo). Utilice el tipo cadena cuando defina las rutas de nodo internas. Por ejemplo, considere este elemento en una sopa denominada “espías”:
    {  
       "first_name":"James",
       "last_name":"Bond",
       "address":{  
          "street_number":10,
          "street_name":"downing",
          "city":"london"
       }
     }
    En este caso, “dirección” es un nodo interno porque tiene un contexto secundario. A través del índice en la ruta “dirección”, puede utilizar una consulta like o match para encontrar el valor “ciudad” (“london”) en “dirección”. Por ejemplo:
    SELECT {spies:first_name, spies:last_name} FROM spies WHERE {spies:address} LIKE 'london'

Formato de archivo de configuración

Éste es un ejemplo teórico de un archivo de configuración de JSON que define dos sopas (soup1 y soup2) y demuestra la gama completa de tipos de datos de índice.

{  "soups": [
    {
      "soupName": "soup1",
      "indexes": [
        { "path": "stringField1", "type": "string"},
        { "path": "integerField1", "type": "integer"},
        { "path": "floatingField1", "type": "floating"},
        { "path": "json1Field1", "type": "json1"},
        { "path": "ftsField1", "type": "full_text"}
      ]
    },
    {
      "soupName": "soup2",
      "indexes": [
        { "path": "stringField2", "type": "string"},
        { "path": "integerField2", "type": "integer"},
        { "path": "floatingField2", "type": "floating"},
        { "path": "json1Field2", "type": "json1"},
        { "path": "ftsField2", "type": "full_text"}
      ]
    }
  ]
 }

Para obtener más información sobre cómo registrar las sopas con código en vez de archivos de configuración, consulte la guía de desarrollo de Salesforce Mobile SDK.

Nota

Si su código o su archivo de configuración registran una sopa con el mismo nombre, Mobile SDK ignora la definición en el archivo de configuración.

El siguiente archivo de configuración registra una única sopa basándose en registros de cuenta. Esta sopa indexa los campos de nombre, Id. e Id. de propietario. No es obligatorio que los nombres de sopa coincidan con el nombre de un objeto de Salesforce de fuente, pero una alusión obvia es habitualmente una buena opción.

{  "soups": [
    {
      "soupName": "account",
      "indexes": [
        { "path": "Name", "type": "string"},
        { "path": "Id", "type": "string"},
        { "path": "OwnerId", "type": "string"}
      ]
    }
  ]
 }

Inserción o actualización de entradas de sopa

Para insertar o actualizar entradas de sopa, lo que permite que SmartStore determine qué acción es apropiada, use un método de actualización/inserción. Por ejemplo, una aplicación híbrida puede utilizar una de estas versiones de JavaScript:

navigator.smartStore.upsertSoupEntries(isGlobalStore, soupName, 
    entries[], successCallback, errorCallback)
navigator.smartStore.upsertSoupEntries(storeConfig, soupName, 
    entries[], successCallback, errorCallback)

Usted proporciona el nombre de la sopa, una matriz de entradas con formato de cadenas de JSON y funciones de devolución de llamadas de éxito y de error opcionales. La única diferencia entre los dos métodos es el primer parámetro. Si su sopa se encuentra en un almacén de usuario o global con nombre, utilice el parámetro storeConfig para proporcionar el tipo de almacén y su nombre. Por ejemplo:

{isGlobalStore:true, name:"AcmeSales"}

Si está utilizando el almacén de usuario o global predeterminado, puede simplemente pasar true para indicar un almacén global. De lo contrario, puede omitir el argumento. Este parámetro es opcional y se establece de forma predeterminada como false. No está presente en métodos nativos, que leen la misma información desde objetos relacionados.

Consulta y gestión de SmartStore

Mobile SDK para aplicaciones nativas de iOS proporciona métodos de fábrica que crean objetos “especificaciones de consulta” basándose en su entrada. Los métodos de generador crean consultas basadas en los siguientes operadores WHERE:

  • = ("exact" operator)
  • LIKE
  • MATCH (extensión de búsqueda de texto completa)
  • BETWEEN, <=, >= (consultas de intervalo)
  • ALL

Estos objetos de consulta gestionan consultas sencillas y le ahorran la molestia de redactarlas por sí mismo. Para subir el matiz en situaciones más complejas, puede redactar su propia consulta de Smart SQL y pasarla al método de generador de Smart SQL. Tras obtener un objeto de consulta, lo pasa a un método de ejecución para recuperar los datos de sopa especificados.

Gestión de una sopa

En ocasiones desea limpiar datos no utilizados o mejorar el desempeño de una sopa cambiando sus índices. Para dichas tareas, SmartStore proporciona un conjunto de métodos que realizan tareas de diagnóstico, mantenimiento y gestión. Utilice estos métodos para obtener información acerca de una sopa o un almacén, modificar la estructura de una sopa o eliminar sopas y almacenes.

Más concretamente, con estos métodos, puede:

  • Conseguir el tamaño de la base de datos subyacente
  • Conseguir una lista de todos los almacenes (usuario o global)
  • Comprobar si existe una sopa con el nombre proporcionado
  • Recuperar las especificaciones de una sopa y sus especificaciones de índice
  • Alterar la configuración de una sopa
  • Volver a indexar una sopa
  • Borrar todos los registros de una sopa
  • Eliminar una sopa del almacén
  • Eliminar un almacén
  • Eliminar todos los almacenes (usuario o global)

Estos métodos están disponibles en todas las plataformas para todos los tipos de aplicación.

Uso de SmartStore Inspector

Durante las pruebas, es importante ver si su código está gestionando los datos de SmartStore como debe. SmartStore Inspector proporciona una herramienta de interfaz de usuario que permite realizar esta comprobación. Con este componente, puede hacer lo siguiente:

  • Examinar metadatos de sopa, como nombres y especificaciones de índice de cualquier sopa
  • Borrar el contenido de una sopa
  • Realizar consultas Smart SQL

Para un acceso más sencillo, inicie SmartStore Inspector a través del cuadro de diálogo Dev Support. 

El modo en que puede acceder al menú de Dev Support depende de su entorno de desarrollo. Para iniciar el cuadro de diálogo, utilice una de las siguientes opciones.

Android

Realice una de las siguientes acciones:

  • Cuando su aplicación se ejecuta en el emulador de Android, utilice el acceso directo de teclado Command+m (Mac) o Ctrl+m (Windows).
  • En un shell de comando de sistema, ejecute: adb shell input keyevent 82.

iOS

  • En un dispositivo físico, utilice el gesto de agitar para abrir el menú de Dev Support y luego seleccione SmartStore Inspector.
  • En el simulador de iOS, seleccione el elemento de menú Hardware > Shake Gesture (Gesto de agitar) o utilice el acceso directo de teclado ^+Command+z.

Uso de SmartStore en aplicaciones iOS nativas

La incorporación del módulo SmartStore en nuevas aplicaciones iOS nativas no requiere ningún esfuerzo adicional. Cualquier aplicación forceios nativa que cree incluye automáticamente la biblioteca SmartStore.

Registro de sopas con un archivo de configuración

Para aplicaciones iOS nativas, Mobile SDK busca archivos de configuración en / (nivel superior) en el paquete Recursos.

  1. Agregue archivos de configuración a su proyecto.
    1. En el navegador de proyectos de Xcode, seleccione el nodo del proyecto.
    2. En la ventana Editor, seleccione Build Phases (Construir fases).
    3. Amplíe Copy Bundle Resources (Copiar recursos de paquete).
    4. Haga clic en + (“Agregar elementos”).
    5. Seleccione su archivo de configuración de sopa. Si su archivo no está aún en una carpeta de proyecto de Xcode:
      1. Para seleccionar su archivo en Finder, haga clic en Agregar otro....
      2. Cuando se le solicite crear grupos, haga clic en Finalizar.
  2. Agregue una única línea de código para cada archivo que proporcione.
    • Para cargar un archivo userstore.json, utilice uno de los siguientes:
      SmartStoreSDKManager.shared().setupUserStoreFromDefaultConfig()
    • Para cargar un archivo globalstore.json, utilice uno de los siguientes:
      SalesforceManager.shared().setupGlobalStoreFromDefaultConfig()

Llenado de una sopa

Cuando registra una sopa, crea una estructura con nombre vacía en la memoria a la espera de datos. A fin de completar la sopa con datos de Salesforce, use el mecanismo de solicitud REST estándar para obtener los datos. Cuando llega la respuesta REST correcta, los datos se extraen del objeto de respuesta y, a continuación, se actualizan e insertan en la sopa. Para consultar los detalles de programación, consulte el ejemplo al final de esta sección iOS.

Consulta de datos de sopa

En iOS, usted crea objetos de especificaciones de consulta llamando métodos de clase en la clase SFQuerySpec. Por ejemplo, en Objective-C, el método newSmartQuerySpec:withPageSize: devuelve un objeto SFQuerySpec que encapsula una cadena de consulta concreta de Smart SQL:

var querySpec = store.buildSmartQuerySpec(
    smartSql: "select {account:Name} from {account}",
    pageSize: 10)

El parámetro de tamaño de página determina el número de registros que se envían en cada página de resultados. Estos métodos permiten un grado de flexibilidad mayor que otras funciones de generador de consultas, ya que usted proporciona su propia instrucción Smart SQL SELECT. Por ejemplo, el siguiente código genera una consulta que llama a la función SQL COUNT. Puesto que COUNT devuelve un valor sencillo, el único tamaño de página posible es uno.

El siguiente código genera una consulta que llama a la función SQL COUNT. Puesto que COUNT devuelve un valor sencillo, el único tamaño de página posible es uno.

Para ejecutar una consulta, pase su objeto SFQuerySpec al método query() en el objeto SFSmartStore.

var querySpec = store.buildSmartQuerySpec(
    smartSql: "select count(*) from {employees}",
    pageSize: 1)

Gestión de una sopa

Para usar las API de gestión de sopa de Objective-C en una aplicación iOS nativa, importe SmartStore/SFSmartStore.h. Llame a los métodos de gestión de sopa en una instancia compartida de SFSmartStore. Obtenga la instancia compartida mediante el uso de uno de los siguientes métodos de clase SFSmartStore.

Si desea obtener la instancia de SmartStore para el usuario actual:

var store = SmartStore.shared(withName:storeName)

Si desea obtener la instancia de SmartStore para un usuario especificado:

var store = SmartStore.shared(withName:storeName, forUserAccount:user)

Por ejemplo, para llamar al método de gestión removeSoup::

self.store = [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName];
 if ([self.store soupExists:@"Accounts"]) {
    [self.store removeSoup:@"Accounts"];
 }

Ejemplo

En este ejemplo, se crea una aplicación de Swift. Esta plantilla de Swift nativa para forceios ya incluye una implementación de SmartStore, así que solo revisaremos su configuración. 

  1. Utilizando forceios, cree un proyecto nativo Swift parecido al siguiente ejemplo:
    $ forceios create Enter your application type (native_swift or native, leave empty for native_swift):<Press RETURN>
    Enter your application name:<Enter any name you like>
    Enter your package name:com.myapps.ios
    Enter your organization name (Acme, Inc.):MyApps.com
    Enter output directory for your app (leave empty for the current directory):<Press RETURN or enter a directory name>
  2. Abra el archivo .xcworkspace de su aplicación en Xcode.
  3. En la carpeta del proyecto, expanda Supporting Files (Archivos compatibles).
  4. Abra el archivo userstore.json e inspeccione la configuración de SmartStore.
  5. Para agregar el archivo de configuración al paquete compilado de la aplicación, en la plantilla, se mencionan estos archivos en Project Settings (Configuración del proyecto).
    1. En el navegador de proyectos de Xcode, seleccione el nodo principal del proyecto.
    2. En la ventana Editor, seleccione Build Phases (Construir fases).
    3. Amplíe Copy Bundle Resources (Copiar recursos de paquete).
    4. Observe que userstore.json está incluido en la lista.
  6. En la carpeta del código fuente de su proyecto, seleccione Classes/SceneDelegate.swift.
  7. En el método scene(_:willConnectTo:options:), busque la llamada a setupRootViewController().
  8. Para ver dónde se cargan los archivos de configuración de SmartStore, pulse la tecla Control y mientras hace clic en setupRootViewController() y seleccione Jump to Definition (Saltar a definición).

Para ver la configuración de SmartStore de la aplicación en el tiempo de ejecución: 

  1. Inicie la aplicación.
  2. Después de registrarse correctamente y de autorizar la aplicación, abra el menú Herramientas de Developer.
    1. Pulse control + comando + z si está utilizando el emulador de iOS, o agite su dispositivo iOS.
    2. Haga clic en Inspect SmartStore (Inspeccionar SmartStore).
    3. Para enumerar sus sopas y la cantidad de registros, haga clic en Soups (Sopas).

Uso de SmartStore en aplicaciones Android nativas

De manera predeterminada, todas las aplicaciones nativas forcedroid incluyen bibliotecas SmartStore y Mobile Sync. No obstante, las aplicaciones Android existentes pueden requerir algunos pasos de configuración personalizada.

  1. En su proyecto Android nativo, abra MainApplication.java.
  2. Agregue la siguiente instrucción de importación si aún no está presente:
    import com.salesforce.androidsdk.mobilesync.app.MobileSyncSDKManager;
  3. Localice la línea que llama a initNative(). Por ejemplo:
    SalesforceSDKManager.initNative(getApplicationContext(), new NativeKeyImpl(), MainActivity.class);
  4. Si initNative() se llama en SalesforceSDKManager, cambie SalesforceSDKManager a MobileSyncSDKManager:
    MobileSyncSDKManager.initNative(getApplicationContext(), new NativeKeyImpl(), MainActivity.class);

Registro de sopas con un archivo de configuración

  1. Coloque sus archivos de configuración de sopas en la carpeta de proyecto /res/raw/.
  2. Agregue una única línea de código para cada archivo que proporcione.
    • Para cargar un archivo userstore.json, utilice
      SmartStoreSDKManager.getInstance().setupUserStoreFromDefaultConfig();
    • Para cargar un archivo globalstore.json, utilice
      SmartStoreSDKManager.getInstance().setupGlobalStoreFromDefaultConfig();

Llenado de una sopa

Cuando registra una sopa, crea una estructura con nombre vacía en la memoria a la espera de datos. Para completar la sopa con datos de Salesforce, use el mecanismo de solicitud REST estándar para obtener los datos. Cuando llega la respuesta REST correcta, los datos se extraen del objeto de respuesta y, a continuación, se actualizan e insertan en la sopa:

public void populateAccounts() throws UnsupportedEncodingException {
    final RestRequest restRequest =
        RestRequest.getRequestForQuery(
            ApiVersionStrings.getVersionNumber(SalesforceSDKManager.getInstance().getAppContext()), 
            "SELECT Name, Id, OwnerId FROM Account");
    client.sendAsync(restRequest, new RestClient.AsyncRequestCallback() {
        @Override
        public void onSuccess(RestRequest request, RestResponse result) {
            result.consumeQuietly(); // always call before switching to main thread (unlike here)
            try {
                JSONArray records = result.asJSONObject().getJSONArray("records");
                insertAccounts(records);
            } catch (Exception e) {
                onError(e);
            } finally {
                Log.println(Log.INFO, "REST Success!", "\nSmartStore insertion successful");
            }
        }
        @Override
        public void onError(Exception e)
        {
            Log.e(TAG, e.getLocalizedMessage());
        }
    });
 }
/**
 * Inserts accounts into the accounts soup.
 *
 * @param accounts Accounts.
 */
 public void insertAccounts(JSONArray accounts)
 {
    try {
        if (accounts != null) {
            for (int i = 0; i < accounts.length(); i++) {
                if (accounts.get(i) != null) {
                    try {
                        smartStore.upsert("Accounts", accounts.getJSONObject(i));
                    }
                    catch (JSONException exc) {
                        Log.e(TAG, "Error occurred while attempting to insert account. "
                                +  "Please verify validity of JSON data set.");
                    }
                }
            }
        }
    }
    catch (JSONException e) {
        Log.e(TAG, "Error occurred while attempting to insert accounts. "
                + "Please verify validity of JSON data set.");
    }
 }

Consulta de datos de sopa con Smart SQL

En Android, usted crea objetos de especificaciones de consulta llamando métodos de generador estáticos en la clase QuerySpec. Por ejemplo, el método buildSmartQuerySpec crea un objeto Smart SQL que encapsula una cadena de consulta concreta:

public static QuerySpec buildSmartQuerySpec(String smartSql, int pageSize)

Para ejecutar la consulta, pase el objeto devuelto QuerySpec al método SmartStore.query(). Esta función permite un grado de flexibilidad mayor que otras funciones de generador de consultas, ya que proporciona su propia instrucción Smart SQL SELECT. El parámetro pageSize determina el número de registros que se envían en cada página de resultados.

Para ejecutar una consulta a través de un objeto QuerySpec, pásela al método query() en el objeto SmartStore. El siguiente código genera una consulta que llama a la función SQL COUNT. Puesto que COUNT devuelve un valor sencillo, el único tamaño de página posible es uno.

try {
    JSONArray result =
        store.query(QuerySpec.buildSmartQuerySpec(
            "select count(*) from {Accounts}", 1), 0);
    // result should be [[ n ]] if there are n employees
    Log.println(Log.INFO, "REST Success!", "\nFound " + 
        result.getString(0) + " accounts.");
 } catch (JSONException e) {
    Log.e(TAG, "Error occurred while counting the number of account records. "
        +  "Please verify validity of JSON data set.");
 }

Gestión de una sopa

Para utilizar las API de gestión de sopa en una aplicación de Android nativa, llama a métodos en la instancia compartida de SmartStore:

SmartStore smartStore = 
    SmartStoreSDKManager.getInstance().getSmartStore();
 smartStore.clearSoup("user1Soup");

Puede agregar fácilmente la compatibilidad de SmartStore a una aplicación nativa de forcedroid. Configuremos el archivo de importación de JSON para crear dos sopas, una para cada consulta de sObject. A continuación podemos rellenar las sopas al mismo tiempo que rellenamos la vista de lista.

  1. Abra su directorio de proyectos en Android Studio.
  2. En la carpeta app/res, cree una carpeta denominada “raw”.
  3. Haga clic con el botón derecho en app/res/raw y seleccione New (Nuevo) > File (Archivo). Asigne un nombre al archivo userstore.json.
  4. Agregue el siguiente texto al nuevo archivo:
    { "soups": [
        {
        "soupName": "Account",
        "indexes": [
            { "path": "Name", "type": "string"},
            { "path": "Id", "type": "string"},
            { "path": "OwnerId", "type": "string"},
            ]
        },
        {
        "soupName": "Contact",
        "indexes": [ 
            { "path": "Name", "type": "string"},
            { "path": "Id", "type": "string"},
            { "path": "OwnerId", "type": "string"},
            ]
        }
     ]}
  5. Abra MainActivity.java e importe estos archivos:
    import com.salesforce.androidsdk.smartstore.app.SmartStoreSDKManager;
     import com.salesforce.androidsdk.smartstore.store.IndexSpec;
     import com.salesforce.androidsdk.smartstore.store.QuerySpec;
     import com.salesforce.androidsdk.smartstore.store.SmartStore;
     import com.salesforce.androidsdk.smartstore.ui.SmartStoreInspectorActivity;
  6. En la parte superior de la clase MainActivity, declare una variable privada para señalar la instancia compartida SmartStore y otra para realizar un seguimiento del sObject que estamos gestionando:
    private SmartStore smartStore;private String objectType;
  7. En el método onCreate(Bundle savedInstanceState), importe las definiciones de sopa desde su archivo userstore.json:
    smartStore = SmartStoreSDKManager.getInstance().getSmartStore();
     if (!smartStore.hasSoup("Account") && !smartStore.hasSoup("Contact")) {
        SmartStoreSDKManager.getInstance().setupUserStoreFromDefaultConfig();
     } else {
        // Delete existing records in preparation for new server data
        smartStore.clearSoup("Account");
        smartStore.clearSoup("Contact");
     }
  8. En el método onFetchContactsClick(View v), deje en blanco la sopa Contact (Contacto) para evitar crear registros duplicados:
    smartStore.clearSoup("Contact");
    objectType = "Contact";
  9. En el método onFetchAccountsClick(View v), deje en blanco la sopa Account (Cuenta) para evitar crear registros duplicados:
    smartStore.clearSoup("Account");
    objectType = "Account";
  10. En el método client.sendAsync(), llame a upsert() en el bucle for que inserta la respuesta de JSON en el objeto listAdapter:
    for (int i = 0; i < records.length(); i++) {
         listAdapter.add(records.getJSONObject(i).getString("Name"));
        try {
             smartStore.upsert((objectType, records.getJSONObject(i));
         } catch (Exception e) {
             onError(e);
         }
    }
  11. Inicie la aplicación y luego compruebe su trabajo utilizando el menú Herramientas de Developer.
    • Para abrir el menú, pulse Comando + m (Mac) o Ctrl + m (Windows).
    • Haga clic en Inspect SmartStore (Inspeccionar SmartStore).
    • Para ver una lista de sus sopas y número de registros en cada una, haga clic en Sopas.
  12. Nota: Si obtiene “Consulta: No se encontraron sopas”, existen posibilidades de que tenga un error en su archivo userstore.json.

Ahora creó y rellenó dos sopas de SmartStore, pero en este punto no sirven para un fin útil. En el mundo real, usted crea una interfaz de modificación para las listas Cuenta y Contacto, y luego inserta los cambios del cliente en SmartStore. Cuando el dispositivo del cliente retomó la conectividad, pudo entonces combinar cambios en el servidor con Mobile Sync.

Uso de SmartStore en aplicaciones híbridas

Registro de sopas con un archivo de configuración

En aplicaciones híbridas, Mobile SDK carga automáticamente los archivos de configuración de SmartStore. Usted es responsable de poner los archivos de configuración en la ubicación obligatoria de la manera siguiente:

  1. Copie el archivo de configuración al directorio de nivel superior www/ de su proyecto híbrido (por ejemplo, MiProyecto/www/).
  2. En una ventana Terminal o en el símbolo del sistema de Windows, utilice cd para cambiar a su directorio de proyecto (por ejemplo, MiProyecto/).
  3. Ejecute: cordova prepare

Llenado de una sopa

Para obtener registros de Salesforce, las aplicaciones híbridas utilizan la función force.query() estándar desde la biblioteca de JavaScript. Utiliza la devolución de llamadas de éxito para insertar los datos desde el registro establecido en la sopa.

force.query("SELECT Name,Id FROM Contact", 
    onSuccessSfdcContacts, onErrorSfdc); 
var sfSmartstore = function() {
    return cordova.require("com.salesforce.plugin.smartstore");};
function onSuccessSfdcContacts(response) {
    logToConsole()("onSuccessSfdcContacts: received " + 
        response.totalSize + “ contacts");
    var entries = [];
    response.records.forEach(function(contact, i) {
           entries.push(contact);
    });
    if (entries.length > 0) {
        sfSmartstore().upsertSoupEntries(CONTACTS_SOUP_NAME,
            entries,
            function(items) {
                var statusTxt = "upserted: " + items.length + 
                    " contacts";
                logToConsole()(statusTxt);
            }, 
         onErrorUpsert);
    }
 }
function onErrorSfdc(param) {
    logToConsole()("onErrorSfdc: " + param);
 }
function onErrorUpsert(param) {
    logToConsole()("onErrorUpsert: " + param);
 }

Consulta de datos de sopa con Smart SQL

En aplicaciones híbridas, crea objetos de especificaciones de consulta llamando a funciones en el objeto SmartStore del complemento com.salesforce.plugin.smartstore. Por ejemplo, la función buildSmartQuerySpec() ejecuta una consulta Smart SQL:

smartstore.buildSmartQuerySpec(smartSql, [pageSize])

Aquí, smartSql es la consulta que se va a ejecutar. Esta función permite un grado de flexibilidad mayor que otras funciones de generador de consultas, ya que proporciona su propia declaración SELECT. La propiedad pageSize es opcional y se establece en 10 de forma predeterminada.

El siguiente código genera una consulta que llama a la función Smart SQL COUNT en una sopa denominada “empleados”.

var querySpec = 
    navigator.smartstore.buildSmartQuerySpec(
        "select count(*) from {employees}", 1);
navigator.smartstore.runSmartQuery(querySpec, function(cursor) { 
    // result should be [[ n ]] if there are n employees
 });

Gestión de una sopa

Cada función de gestión de sopa de JavaScript usa dos funciones de devolución de llamada: una devolución de llamada correcta que devuelve los datos solicitados y una devolución de llamada con errores. Las devoluciones de llamada correcta varían según las funciones de gestión de sopa que las usen. Las devoluciones de llamada con errores usan un solo argumento, el cual contiene una cadena de descripción de error. Por ejemplo, puede definir una función de devolución de llamada del modo siguiente:

function(e) { alert(“ERROR:“ + e);}

Para llamar a una función de gestión de sopa en JavaScript, invoque en primer lugar el complemento Cordova para inicializar el objeto SmartStore. A continuación, use el objeto SmartStore para llamar a la función de gestión de sopa. En el siguiente ejemplo se definen funciones de devolución de llamada de forma discreta, pero también puede definirlas en línea y de forma anónima.

var sfSmartstore = function() {
    return cordova.require("com.salesforce.plugin.smartstore");};
function onSuccessRemoveSoup(param) {
    logToConsole()("onSuccessRemoveSoup: " + param);
    $("#div_soup_status_line").html("Soup removed: " 
        + SAMPLE_SOUP_NAME);
 }
function onErrorRemoveSoup(param) {
    logToConsole()("onErrorRemoveSoup: " + param);
    $("#div_soup_status_line").html("removeSoup ERROR");
 }
sfSmartstore().removeSoup(SAMPLE_SOUP_NAME,
     onSuccessRemoveSoup, 
     onErrorRemoveSoup);

Uso de SmartStore en aplicaciones React Native

Las aplicaciones React Native tienen mucho en común con aplicaciones híbridas. Habitualmente, las funciones de SmartStore para las dos plataformas comparten firmas idénticas. Sin embargo, se aplican varias diferencias significativas.

  • Las aplicaciones React Native utilizan código JavaScript ES2015. Aunque puede utilizar la misma sintaxis de JavaScript como en aplicaciones híbridas, también puede aprovechar las nuevas convenciones de codificación simplificada.
  • Además de JavaScript, las aplicaciones React Native también admiten TypeScript para escritura estática. Puede elegir en qué medida lo usará, o si en realidad usará TypeScript.
  • En React Native, SmartStore no utiliza backbone.js.
  • No puede utilizar complementos o bibliotecas híbridas de Cordova en React Native. En su lugar, importe módulos de React Native SmartStore.

Para utilizar la API de SmartStore, importe el módulo smartstore. Para utilizar la API de Salesforce (más importante para la realización de consultas para recuperar registros de Salesforce) importa el módulo net. Puede importar ambos módulos en una única declaración:

import {net, smartstore} from 'react-native-force';

Registro de una sopa

Para React Native, debe utilizar código JavaScript en vez de archivos de configuración a fin de configurar sopas de SmartStore. Por ejemplo:

smartstore.registerSoup(false,
    "contacts", 
    [ {path:"Id", type:"string"}, 
    {path:"FirstName", type:"full_text"}, 
    {path:"LastName", type:"full_text"},    
    {path:"__local__", type:"string"} ],
    () => syncDown()
 );

Llenado de una sopa

Para llenar su sopa con datos de Salesforce, comience por consultar registros utilizando la API estándar de Salesforce. El módulo net proporciona un conjunto de funciones de contenedor que simplifican las llamadas de red. Usted pasa una cadena de consulta y devoluciones de llamadas de éxito y error. En la devolución de llamada de éxito, utiliza el módulo smartstore para insertar registros de la respuesta de consulta en su sopa. (¡Si esta estrategia le suena familiar, debe leer la sección híbrida!)

net.query("SELECT Name,Id FROM Contact", 
        onSuccessSfdcContacts, onErrorSfdc);

Éste es un ejemplo de devolución de llamada de éxito.

function onSuccessSfdcContacts(response) {
    logToConsole()("onSuccessSfdcContacts: received " + 
        response.totalSize + “ contacts");
    var entries = [];
    $.each(response.records, function(i, contact) {
           entries.push(contact);
           logToConsole()("name: " + contact.Name);
    });
    if (entries.length > 0) {
        smartstore().upsertSoupEntries(CONTACTS_SOUP_NAME,
            entries,
            function(items) {
                var statusTxt = "upserted: " + items.length + 
                    " contacts";
                logToConsole()(statusTxt);
            }, 
            onErrorUpsert);
    }
 }

Consulta de datos de sopa con Smart SQL

En React Native, crea objetos de especificaciones de consulta llamando funciones en el módulo smartstore. Por ejemplo, la función buildSmartQuerySpec() crea un objeto de consulta Smart SQL:

buildSmartQuerySpec(smartSql, [pageSize])

En esta función, smartSql es la consulta que se va a ejecutar. Esta función permite un grado de flexibilidad mayor que otras funciones de generador de consultas, ya que proporciona su propia declaración SELECT. La propiedad pageSize es opcional y se establece en 10 de forma predeterminada.

Una vez haya creado el objeto de consulta inteligente, lo pasa a la función runSmartQuery(), proporcionando una devolución de llamadas de éxito para gestionar la respuesta. El siguiente código crea y ejecuta una consulta que llama a la función SQL COUNT.

var querySpec = 
    smartstore.buildSmartQuerySpec(
        "select count(*) from {employees}", 1);
// Note that the first parameter--a storeConfig object, or a Boolean indicating whether to use 
// the default global store or the default user store--is required in React Native apps
// but is optional in hybrid apps
smartstore.runSmartQuery(false, querySpec, function(cursor) { 
    // result should be [[ n ]] if there are n employees
 });

Uso de funciones de gestión de SmartStore

Las funciones de gestión de sopa siguen el mismo patrón que otras funciones de React Native. Usted define las devoluciones de llamadas de éxito y error y llama la función en el módulo smartstore. El número de parámetros pasados a la devolución de llamadas de éxito puede variar dependiendo de la función. Las devoluciones de llamadas de error solo utilizan un argumento de cadena de descripción de error.

Recursos

¡Siga aprendiendo gratis!
Regístrese para obtener una cuenta y continuar.
¿Qué hay para usted?
  • Consiga recomendaciones personalizadas para sus objetivos profesionales
  • Practique sus aptitudes con retos prácticos y pruebas
  • Siga y comparta su progreso con empleadores
  • Póngase en contacto para recibir asesoramiento y oportunidades laborales