Realm是什么类型的数据库?

时间:2017-02-20 05:48:08

标签: ios database realm

Realm 是什么类型的数据库?是 ORM 吗?或者它像对象数据库一样工作?也许数据库结构会以某种方式影响设计过设计Realm数据库有什么细微差别吗?

我在这里问,因为我在官方网站上找不到任何答案

1 个答案:

答案 0 :(得分:3)

不幸的是我实际上并没有使用 iOS 版本,但我确实使用的是Android版本,它在iOS版本的功能集中越来越相似,并且它们共享相同的core,他们更接近通过object-store提供相同的统一行为。

因此,大部分答案都将基于Swift API文档。 (Realm Swift 2.6.1)

Realm默认为对象存储。从技术上讲,它将您的数据存储在模式中,模式由类定义,如

// from https://realm.io/docs/swift/latest/#models
class Person: Object {
    dynamic var name = ""
    dynamic var birthdate = NSDate(timeIntervalSince1970: 1)
    let dogs = List<Dog>()
}

现在Realm的有趣之处在于它不是关系数据库;它直接存储对象。实际上,由Realm管理的对象(也就是通过对Realm的查询获得的对象,或由Realm创建的新创建的对象)直接映射到底层的Realm文件,并且不将数据复制到字段,访问者直接读取和写入领域文件。

这&#34;直接访问&#34;导致所有数据仅在访问时加载(延迟评估),因此不需要缓存托管对象(!)。

所有写入都是事务性的。在事务之外,无法修改托管的RealmObject。

在您的对象之间,您可以拥有关系(链接):

// from https://realm.io/docs/swift/latest/#relationships
class Dog: Object {
    // ... other property declarations
    dynamic var owner: Person? // to-one relationships must be optional
}

class Person: Object {
    // ... other property declarations
    let dogs = List<Dog>() // to-many relationship
}

任何关系(to-one,to-many)都有相应的backlink,您可以将其定义为&#34;链接到此对象的对象&#34;。

// from https://realm.io/docs/swift/latest/#relationships
class Dog: Object {
    dynamic var name = ""
    dynamic var age = 0
    let owners = LinkingObjects(fromType: Person.self, property: "dogs")
}

Realm的托管对象是&#34;实时,不可变的数据视图&#34; (来自here),变异,您通过notification token (来自here)收到有关此变更通知。这同样适用于任何托管的RealmObject ,但也会查询结果

意思是,查询结果会自动异步评估,并且只能以延迟加载的方式从数据库中读取在给定索引处访问的元素!因此,不需要分页。

任何线程上的任何写操作都会自动向与运行循环关联的线程发送通知,并自动更新查询结果,并调用更改侦听器(通知块)。

// from https://realm.io/docs/swift/latest/#collection-notifications
  override func viewDidLoad() {
    super.viewDidLoad()
    let realm = try! Realm()
    let results = realm.objects(Person.self).filter("age > 5")

    // Observe Results Notifications
    notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
      guard let tableView = self?.tableView else { return }
      switch changes {
      case .initial:
        // Results are now populated and can be accessed without blocking the UI
        tableView.reloadData()
        break
      case .update(_, let deletions, let insertions, let modifications):
        // Query results have changed, so apply them to the UITableView
        tableView.beginUpdates()
        tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }),
                           with: .automatic)
        tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}),
                           with: .automatic)
        tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }),
                           with: .automatic)
        tableView.endUpdates()
        break
      case .error(let error):
        // An error occurred while opening the Realm file on the background worker thread
        fatalError("\(error)")
        break
      }
    }
  }

  deinit {
    notificationToken?.stop()
  }

最着名的限制是RealmObjects,RealmResults和Realms 不能在线程之间传递。 (其他限制是here)。

给定线程上的RealmObject / RealmResults / Realm只能在打开其相应Realm实例的线程上访问(读取here)。 (例外是使用ThreadSafeReference在线程之间发送的RealmObjects,请参阅here)。

因此,后台线程需要自己的Realm实例,通常包含在autoreleasepool中,请参阅here

// from https://realm.io/docs/swift/latest/#using-a-realm-across-threads
DispatchQueue(label: "background").async {
  autoreleasepool {
    // Get realm and table instances for this thread
    let realm = try! Realm()

    // Break up the writing blocks into smaller portions
    // by starting a new transaction
    for idx1 in 0..<1000 {
      realm.beginWrite()

      // Add row via dictionary. Property order is ignored.
      for idx2 in 0..<1000 {
        realm.create(Person.self, value: [
          "name": "\(idx1)",
          "birthdate": Date(timeIntervalSince1970: TimeInterval(idx2))
        ])
      }

      // Commit the write transaction
      // to make this data available to other threads
      try! realm.commitWrite()
    }
  }
}