Android上的NoSQL

有多种针对移动平台(例如iOS和Android)的NoSQL解决方案。 在这里,我们将研究Couchbase Lite (CDB – TouchDB的后继产品),这是一个轻量级的,功能齐全的嵌入式JSON数据库。

为什么要使用功能全面的数据库,而不仅仅是云服务的包装器? 基本上是响应能力 这个想法是即使网络中断或速度很慢,该应用程序也应始终对用户可用。 当然,能够在本地处理数据也意味着我们必须在某个时候与服务器同步

请注意,尽管有“ Couch”部分,但CBL 与 Apache CouchDB有很大不同 。

现在,让我们开始做生意,创建一个小型Android应用程序(整个代码在GitHub上可用 ),该应用程序使用CBL的Native API设置数据库并运行基本的CRUD操作。

在经历了相对简单的设置之后( 这是针对老Eclipse用户的, 那是针对Android Studio爱好者的),让我们从编写一些代码开始:

import com.couchbase.lite.*;
import com.couchbase.lite.android.AndroidContext;

/** Database wrapper*/
public class CbDatabase {

  private Database database;
  private Manager manager;

  /** Ctor Setup */
  public CbDatabase(String dbname) 
                    throws IOException, CouchbaseLiteException {
      
     // 1. use default settings (read/write access)
     manager = new Manager( new AndroidContext(ctx),  
                            Manager.DEFAULT_OPTIONS );

     // 2. Check database name given by user
     // No upper case allowed in CBL!
     // Only the following characters are valid: 
     // abcdefghijklmnopqrstuvwxyz0123456789_$()+-/

     if ( ! Manager.isValidDatabaseName(dbname)) {
         // report...
         return;
     }	
     // 3. Get existing db with that name
     // or create a new one if it doesn't exist
      database = manager.getDatabase(dbname);
  }

  //...more methods to come
}

上面的代码使用Manager来设置具有有效名称的数据库。 CBL数据库基本上是文档的容器。 管理器可以创建几个不同的数据库,每个数据库都有自己的名称空间。 这是释放所有资源的方法:

/** */
public void close(){
  if(manager != null){
    manager.close();
  }
}

一旦给了数据库对象,我们就可以对它进行CRUD操作了:

/** C-rud */
public String create( Map docContent )
                       throws CouchbaseLiteException {

  // create an empty document
  Document doc = database.createDocument();
  // add content to document and save it
  doc.putProperties(docContent);
  return doc.getId();
}

CBL 文档是存储在数据库中的主要实体,并具有以下属性:

  • 唯一ID(_id属性),可以自动生成为UUID
  • 修订ID(_rev属性)以跟踪更新
  • 一组构成文档主体的键/值对

创建完成后,我们可以通过其ID检索文档的内容:

/** c-R-ud */
public Map retrieve(String docId){
  return database.getDocument(docId)
         .getProperties();
}

我们可以使用回调更新文档中现有的键/值对条目:

/** cr-U-d (auto-retry) */
public void update( final String key, final Object value, 
                    String docId )
                    throws CouchbaseLiteException {

   // retrieve the document from the database
   Document doc = database.getDocument(docId);
   doc.update(new Document.DocumentUpdater() {
       @Override
       /** This may be called more than once */
       public boolean update(UnsavedRevision newRevision) {
           Map properties = newRevision.getUserProperties();
           properties.put(key, value);
           newRevision.setUserProperties(properties);
           return true;
       }
   });
}

在写冲突的情况下,该方法通过重新读取Document并重新调用回调方法来自动重试更新。 该过程将一直持续到写入成功为止。 顾名思义, UnsavedRevision是一个可变副本,可以使用它,直到数据最终持久保存到数据库中为止。
删除文档非常简单。 在这里,我们通过其ID进行操作:

/** cru-D */
public boolean delete(String docId)
                      throws CouchbaseLiteException {

   // retrieve the document from the database
   Document doc = database.getDocument(docId);
   // delete the document
   doc.delete();
   return  doc.isDeleted();
}

删除文档将创建一个新的修订版本,称为“墓碑”(不开玩笑)。 它将被标记为已删除,以便在进行同步时可以将其状态复制到服务器。 至于更新,如果其他用户对同一文档进行更改,则可能导致冲突。 在这种情况下,重试删除的决定留给我们。

现在,我们准备在项目中使用此包装器类。 首先,让我们定义用例:假设我们需要在本地为我们的手机游戏存储一些用户数据,例如用户电子邮件,当用户在我们的系统中注册时以及一系列游戏得分。 这是一个快速测试,我们可以在主Activity的onCreate()方法中运行。 首先,让我们输入一些数据:

// get the current date and time
Date now = new Date();
String nowString = DateFormat.getDateTimeInstance(
DateFormat.LONG, DateFormat.LONG).format(now);
// game scores
List scores = new ArrayList();
scores.add(190.00);
scores.add(210.00);
scores.add(250.00);
scores.add(275.00);
// create an object that contains data for a document
Map docContent = new HashMap();
docContent.put("email", "[email protected]");
docContent.put("registered", nowString);
docContent.put("scores", scores);

现在,数据库操作:

try{
   CbDatabase db = new CbDatabase("testdb");
   // 1. Create
   String docId = db.create(docContent);
   // 2. Retrieve
   Map docContent = db.retrieve(docId);
   // 3. Update
   scores.add(350.00);
   db.update("scores", scores, docId);
   // 4. Delete
   boolean deleted = db.delete(docId);
   assert(deleted == true);
} 
catch (Exception e) {
   // handle here...
} 
finally{
  if(db != null){
     db.close();
  }
}

以下是用于检索和更新的相应JSON文档:

// retrieved
{ 
  _rev=1-1ef4c4618a712cdf437d4b0c92594ddc, 
  _id=69fdcb83-1774-4a3f-9e88-b298d3c7304a, 
   scores=[190.0, 210.0, 250.0, 275.0], 
   [email protected], 
   registered=June 18, 2014 11:03:18 AM GMT+02:00
}
//--------------------------------------------
// updated scores: note the change in revision 
{ 
  _rev=2-23e6d83d243f80c03b17c4160d511e16, 
   scores=[190.0, 210.0, 250.0, 275.0, 350.0], 
  _id=69fdcb83-1774-4a3f-9e88-b298d3c7304a, 
   [email protected], 
   registered=June 18, 2014 11:03:18 AM GMT+02:00
}

而已。 进一步的代码细节在GitHub上 。 我们只是通过这个非常基本的介绍来介绍CBL的表面。 不幸的是,与iOS相比,目前用于Android的CBL在线文档尚不完善。 无论如何,还有其他重要的CBL功能,例如添加附件,视图和查询,复制(服务器和P2P),REST API等。这些将成为以后文章的主题。

翻译自: https://www.javacodegeeks.com/2014/06/nosql-on-android.html

你可能感兴趣的:(Android上的NoSQL)